summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--.gitmodules3
m---------.mason0
-rw-r--r--.travis.yml161
-rw-r--r--CMakeLists.txt45
-rw-r--r--INSTALL.md2
-rw-r--r--Makefile157
-rw-r--r--benchmark/api/query.benchmark.cpp10
-rw-r--r--benchmark/src/mbgl/benchmark/util.cpp4
-rw-r--r--bin/render.cpp26
-rw-r--r--cloudformation/travis.template94
-rw-r--r--cmake/benchmark.cmake6
-rw-r--r--cmake/core-files.cmake126
-rw-r--r--cmake/core.cmake1
-rw-r--r--cmake/glfw.cmake13
-rw-r--r--cmake/loop-darwin.cmake2
-rw-r--r--cmake/mbgl.cmake5
-rw-r--r--cmake/node.cmake5
-rw-r--r--cmake/offline.cmake6
-rw-r--r--cmake/render.cmake1
-rw-r--r--cmake/shaders.cmake12
-rw-r--r--cmake/test-files.cmake6
-rw-r--r--cmake/test.cmake7
-rw-r--r--include/mbgl/gl/implementation.hpp16
-rw-r--r--include/mbgl/map/map.hpp8
-rw-r--r--include/mbgl/math/log2.hpp27
-rw-r--r--include/mbgl/mbgl.hpp4
-rw-r--r--include/mbgl/platform/default/headless_display.hpp29
-rw-r--r--include/mbgl/sprite/sprite_image.hpp4
-rw-r--r--include/mbgl/style/conversion/function.hpp4
-rw-r--r--include/mbgl/style/conversion/make_property_setters.hpp13
-rw-r--r--include/mbgl/style/conversion/make_property_setters.hpp.ejs2
-rw-r--r--include/mbgl/style/filter_evaluator.hpp4
-rw-r--r--include/mbgl/style/function.hpp31
-rw-r--r--include/mbgl/style/layer.hpp6
-rw-r--r--include/mbgl/style/layers/circle_layer.hpp12
-rw-r--r--include/mbgl/style/layers/custom_layer.hpp2
-rw-r--r--include/mbgl/style/layers/fill_extrusion_layer.hpp72
-rw-r--r--include/mbgl/style/property_value.hpp24
-rw-r--r--include/mbgl/style/transition_options.hpp14
-rw-r--r--include/mbgl/util/color.hpp31
-rw-r--r--include/mbgl/util/constants.hpp2
-rw-r--r--include/mbgl/util/event.hpp (renamed from include/mbgl/platform/event.hpp)0
-rw-r--r--include/mbgl/util/exception.hpp5
-rw-r--r--include/mbgl/util/image.hpp43
-rw-r--r--include/mbgl/util/logging.hpp (renamed from include/mbgl/platform/log.hpp)2
-rw-r--r--include/mbgl/util/platform.hpp (renamed from include/mbgl/platform/platform.hpp)0
-rw-r--r--include/mbgl/util/range.hpp2
-rw-r--r--include/mbgl/util/size.hpp32
m---------mapbox-gl-js0
-rw-r--r--package.json15
-rw-r--r--platform/android/.gitignore2
-rw-r--r--platform/android/CHANGELOG.md56
-rw-r--r--platform/android/MapboxGLAndroidSDK/build.gradle241
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/deploy.sh2
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle17
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle-javadoc.gradle21
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle-publish.gradle153
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle.properties8
-rw-r--r--platform/android/MapboxGLAndroidSDK/proguard-rules.pro48
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/BaseGestureDetector.java241
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/MoveGestureDetector.java260
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/RotateGestureDetector.java260
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/ShoveGestureDetector.java317
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/TwoFingerGestureDetector.java356
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java104
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapboxAccountManager.java131
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java195
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java128
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java477
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java90
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/IconFactory.java311
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java501
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowTipView.java94
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowView.java52
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java392
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java249
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java767
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java1041
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java217
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java102
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java90
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java346
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polyline.java90
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolylineOptions.java350
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java497
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java711
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeoConstants.java50
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java269
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java51
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java36
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java98
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/ConversionException.java22
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java8
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java20
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidLatLngBoundsException.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidMarkerPositionException.java10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/MapboxAccountManagerNotStartedException.java23
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TelemetryServiceNotConfiguredException.java11
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TooManyIconsException.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ILatLng.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/IProjectedMeters.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java366
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java556
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java156
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java189
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java219
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java312
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationListener.java11
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java326
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java685
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassViewSettings.java21
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java8
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java158
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/InfoWindowManager.java94
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java325
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java657
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java265
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java3917
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapZoomButtonController.java59
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java3876
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java2138
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java1263
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java17
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java191
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java335
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java498
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java300
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java1450
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java48
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java225
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java1228
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java496
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityListener.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java134
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/NativeConnectivityListener.java38
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java510
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java709
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionDefinition.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionError.java83
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java184
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition.java80
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java171
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CannotAddLayerException.java12
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java426
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java35
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java450
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java422
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Function.java210
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java126
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LayoutProperty.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java588
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/NoSuchLayerException.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PaintProperty.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java919
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java3778
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java77
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java299
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java1436
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/layer.java.ejs10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property.java.ejs2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.java12
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java122
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java318
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/NoSuchSourceException.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java118
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java94
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java575
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java86
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/GzipRequestInterceptor.java70
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java209
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java1336
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java104
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java269
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java160
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java183
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MapFragmentUtils.java56
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java96
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml132
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/color/mapbox_material_bg_selector.xml (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/color/material_bg_selector.xml)0
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_compass_icon.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/compass.png)bin3787 -> 3787 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_logo_icon.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/attribution_logo.png)bin3408 -> 3408 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_marker_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/default_marker.png)bin1520 -> 1520 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_markerview_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/default_markerview.png)bin1669 -> 1669 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_mylocation_icon_bearing.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_bearing.png)bin1046 -> 1046 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_mylocation_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_normal.png)bin885 -> 885 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_compass_icon.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/compass.png)bin2488 -> 2488 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_logo_icon.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/attribution_logo.png)bin1958 -> 1958 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_marker_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/default_marker.png)bin1010 -> 1010 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_markerview_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/default_markerview.png)bin1115 -> 1115 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_mylocation_icon_bearing.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_bearing.png)bin649 -> 649 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_mylocation_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_normal.png)bin555 -> 555 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-v21/mapbox_default_bg_selector.xml (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-v21/bg_default_selector.xml)0
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_compass_icon.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/compass.png)bin4775 -> 4775 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_logo_icon.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/attribution_logo.png)bin4492 -> 4492 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_marker_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/default_marker.png)bin1995 -> 1995 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_markerview_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/default_markerview.png)bin2163 -> 2163 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_mylocation_icon_bearing.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_bearing.png)bin1345 -> 1345 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_mylocation_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_normal.png)bin1096 -> 1096 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_compass_icon.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/compass.png)bin7527 -> 7527 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_logo_icon.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/attribution_logo.png)bin7059 -> 7059 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_mapview_preview.jpg (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapview_preview.jpg)bin166053 -> 166053 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_marker_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/default_marker.png)bin2998 -> 2998 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_markerview_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/default_markerview.png)bin3163 -> 3163 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_mylocation_icon_bearing.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_bearing.png)bin1902 -> 1902 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_mylocation_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_normal.png)bin1586 -> 1586 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_compass_icon.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/compass.png)bin18537 -> 18537 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_infowindow_icon_bg.9.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/bg_infowindow_content.9.png)bin928 -> 928 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_logo_icon.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/attribution_logo.png)bin9402 -> 9402 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_marker_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/default_marker.png)bin4006 -> 4006 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_markerview_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/default_markerview.png)bin4071 -> 4071 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_mylocation_icon_bearing.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_bearing.png)bin3022 -> 3022 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_mylocation_icon_default.png (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_normal.png)bin2456 -> 2456 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/bg_default_selector.xml6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_info_outline_24dp_selector.xml5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_mylocationview_background.xml10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_default_bg_selector.xml6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_bg_selector.xml5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_icon_default.xml (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_info_outline_24dp.xml)0
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_icon_selected.xml (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_info_outline_24dp_selected.xml)0
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_mylocation_bg_shape.xml10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_attribution_list_item.xml (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/layout/attribution_list_item.xml)0
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_infowindow_content.xml (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/layout/infowindow_content.xml)16
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_infowindow_view.xml (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/layout/infowindow_view.xml)0
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_internal.xml)10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_preview.xml (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_preview.xml)22
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_view_image_marker.xml (renamed from platform/android/MapboxGLAndroidSDK/src/main/res/layout/view_image_marker.xml)0
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/arrays.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml99
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml20
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/integers.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml38
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml7
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/build.gradle126
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/gradle-checkstyle.gradle17
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/gradle-config.gradle22
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/gradle-device-farm.gradle43
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/gradle-make.gradle18
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/lint.xml34
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapViewUtils.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java826
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapUtils.java15
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java81
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/AddRemoveMarkerActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/BulkMarkerActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/DynamicMarkerChangeActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewScaleActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolygonActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolylineActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PressForMarkerActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraAnimationTypeActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraPositionActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/LatLngBoundsActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ManualZoomActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/MaxMinZoomActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ScrollByActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/customlayer/CustomLayerActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/directions/DirectionsActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesBoxCountActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesPropertiesActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/geocoding/GeocoderActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/imagegenerator/PrintActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/DynamicInfoWindowAdapterActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowAdapterActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/DebugModeActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/MapPaddingActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/SurfaceViewMediaControlActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/VideoViewActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/offline/OfflineActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CircleLayerActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CustomSpriteActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleTimingTestActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/StyleFileActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java142
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerViewTest.java147
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java105
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java100
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraAnimateTest.java253
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraEaseTest.java252
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraInternalApiTest.java169
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraMoveTest.java252
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/RotateActivityTest.java62
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/TiltActivityTest.java62
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/ZoomActivityTest.java71
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesBoxCountTest.java61
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesHighlightTest.java81
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesPropertiesTest.java78
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedSymbolBoxCountTest.java62
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java156
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java153
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/LogoTest.java84
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/MyLocationViewTest.java246
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerStyleTest.java169
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java169
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BaseStyleTest.java40
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerStyleTest.java433
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java524
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerStyleTest.java474
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java474
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerStyleTest.java735
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java735
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerStyleTest.java389
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java390
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleBackgroundLayerTest.java74
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java219
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTimingTests.java43
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerStyleTest.java2331
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java2331
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs23
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/DrawerUtils.java16
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/GestureUtils.java6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java78
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ScreenshotUtil.java193
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/TestConstants.java18
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ViewUtils.java15
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml40
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java62
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java339
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AddRemoveMarkerActivity.java264
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java412
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java439
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java212
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java786
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewScaleActivity.java229
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewsInRectangleActivity.java133
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java288
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java363
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java217
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java335
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java306
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java211
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java194
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java140
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java220
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java255
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/directions/DirectionsActivity.java316
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/espresso/EspressoTestActivity.java80
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java252
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java236
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java186
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java398
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java106
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MultiMapActivity.java10
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java109
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java138
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/geocoding/GeocoderActivity.java310
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/PrintActivity.java170
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java180
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java255
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowActivity.java336
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java238
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java214
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java279
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java187
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java238
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/NavigationDrawerActivity.java384
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SimpleMapActivity.java86
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SurfaceViewMediaControlActivity.java151
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VideoViewActivity.java102
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/navigation/CarDrivingActivity.java282
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/navigation/LocationPickerActivity.java747
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java589
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.java264
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java247
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CustomSpriteActivity.java238
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java265
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java194
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java913
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTestActivity.java101
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTimingTestActivity.java143
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java35
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java215
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java270
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java374
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java253
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java576
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureAdapter.java66
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java265
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/activity/Feature.java112
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarker.java16
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarkerOptions.java88
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarker.java26
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerOptions.java98
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerView.java26
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java166
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/PulseMarkerView.java6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/PulseMarkerViewOptions.java110
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerView.java16
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerViewOptions.java130
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/constants/AppConstant.java2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer.java19
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java82
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java63
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java27
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java88
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ItemClickSupport.java138
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java43
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimingLogger.java211
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ToolbarComposer.java58
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-hdpi/ic_launcher_round.pngbin0 -> 24697 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-mdpi/ic_launcher_round.pngbin0 -> 14115 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xhdpi/ic_launcher_round.pngbin0 -> 37126 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/ic_launcher_round.pngbin0 -> 66853 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/ic_launcher_round.pngbin0 -> 103015 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_directions_bus_black_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_add_sprite.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animated_marker.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animation_types.xml6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_position.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_test.xml22
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_car_driving.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_circle_layer.xml36
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_circlelayer.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_directions.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_dynamic_marker.xml12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_geocoder.xml6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow_adapter.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow_adapter_dynamic.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_source.xml36
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_simple.xml19
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_bulk.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_in_rect.xml28
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_scale.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_maxmin_zoom.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_dot_color.xml43
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_tracking.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polyline.xml10
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml14
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_features_box.xml6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_features_point.xml12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_scroll_by.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_style_file.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_surfaceview_mediacontrols.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_symbollayer.xml22
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_video_view.xml12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_dialog_map.xml12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_custom_layer.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_symbol_layer.xml16
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/raw/test_points_utrecht.geojson49
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml19
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/AnnotationTest.java122
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/IconTest.java80
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/InfoWindowTest.java130
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java282
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java521
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/PolygonTest.java106
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/PolylineTest.java104
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java211
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/constants/StyleVersionTest.java16
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java363
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngSpanTest.java88
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java356
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/ProjectedMetersTest.java88
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java161
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java335
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java868
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/ProjectionTest.java26
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/TrackingSettingsTest.java95
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java611
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java145
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/style/layers/FilterTest.java170
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/style/layers/FunctionTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/ExponentialBackOffTest.java19
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java15
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/utils/MockParcel.java399
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker1
-rwxr-xr-xplatform/android/MapboxGLAndroidSDKTestApp/update_icons.sh21
-rw-r--r--platform/android/MapboxGLAndroidSDKWearTestApp/build.gradle53
-rw-r--r--platform/android/MapboxGLAndroidSDKWearTestApp/gradle-checkstyle.gradle17
-rw-r--r--platform/android/MapboxGLAndroidSDKWearTestApp/gradle-config.gradle22
-rw-r--r--platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/MapboxApplication.java4
-rw-r--r--platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/activity/FeatureOverviewActivity.java4
-rw-r--r--platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/activity/SimpleMapViewActivity.java16
-rw-r--r--platform/android/MapboxGLAndroidSDKWearTestApp/src/main/res/layout/activity_simple_mapview.xml10
-rw-r--r--platform/android/MapboxGLAndroidSDKWearTestApp/src/test/java/com/mapbox/weartestapp/utils/OffsettingHelperTest.java28
-rw-r--r--platform/android/bitrise.yml85
-rw-r--r--platform/android/build.gradle7
-rw-r--r--platform/android/checkstyle.gradle16
-rw-r--r--platform/android/checkstyle.xml32
-rw-r--r--platform/android/config.cmake286
-rw-r--r--platform/android/gradle/wrapper/gradle-wrapper.jarbin53324 -> 54227 bytes
-rw-r--r--platform/android/gradle/wrapper/gradle-wrapper.properties5
-rwxr-xr-xplatform/android/gradlew22
-rw-r--r--platform/android/gradlew.bat6
-rw-r--r--platform/android/scripts/generate-style-code.js42
-rw-r--r--platform/android/scripts/generate-test-code.js2
-rwxr-xr-xplatform/android/scripts/metrics.sh15
-rw-r--r--platform/android/src/connectivity_listener.cpp2
-rw-r--r--platform/android/src/example_custom_layer.cpp35
-rw-r--r--platform/android/src/geometry/conversion/feature.hpp2
-rw-r--r--platform/android/src/http_file_source.cpp2
-rwxr-xr-xplatform/android/src/jni.cpp104
-rw-r--r--platform/android/src/jni.hpp6
-rw-r--r--platform/android/src/logging_android.cpp (renamed from platform/android/src/log_android.cpp)2
-rw-r--r--platform/android/src/main.cpp9
-rwxr-xr-xplatform/android/src/native_map_view.cpp120
-rwxr-xr-xplatform/android/src/native_map_view.hpp6
-rw-r--r--platform/android/src/run_loop.cpp2
-rw-r--r--platform/android/src/style/android_conversion.hpp2
-rw-r--r--platform/android/src/style/conversion/geojson.hpp2
-rw-r--r--platform/android/src/style/conversion/types.hpp2
-rw-r--r--platform/android/src/style/conversion/types.hpp.ejs2
-rw-r--r--platform/android/src/style/conversion/types_string_values.hpp2
-rw-r--r--platform/android/src/style/conversion/types_string_values.hpp.ejs2
-rw-r--r--platform/android/src/style/layers/background_layer.cpp2
-rw-r--r--platform/android/src/style/layers/background_layer.hpp2
-rw-r--r--platform/android/src/style/layers/circle_layer.cpp25
-rw-r--r--platform/android/src/style/layers/circle_layer.hpp8
-rw-r--r--platform/android/src/style/layers/custom_layer.cpp2
-rw-r--r--platform/android/src/style/layers/fill_layer.cpp2
-rw-r--r--platform/android/src/style/layers/fill_layer.hpp2
-rw-r--r--platform/android/src/style/layers/layer.cpp27
-rw-r--r--platform/android/src/style/layers/layer.cpp.ejs4
-rw-r--r--platform/android/src/style/layers/layer.hpp18
-rw-r--r--platform/android/src/style/layers/layer.hpp.ejs4
-rw-r--r--platform/android/src/style/layers/line_layer.cpp2
-rw-r--r--platform/android/src/style/layers/line_layer.hpp2
-rw-r--r--platform/android/src/style/layers/raster_layer.cpp2
-rw-r--r--platform/android/src/style/layers/raster_layer.hpp2
-rw-r--r--platform/android/src/style/layers/symbol_layer.cpp2
-rw-r--r--platform/android/src/style/layers/symbol_layer.hpp2
-rw-r--r--platform/android/src/style/sources/source.cpp23
-rw-r--r--platform/android/src/style/sources/source.hpp16
-rw-r--r--platform/android/src/test/Main.java15
-rw-r--r--platform/android/src/test/main.jni.cpp101
-rw-r--r--platform/android/src/thread.cpp4
-rw-r--r--platform/android/tests/README.md9
-rw-r--r--platform/android/tests/docs/ACTIVITY_SANITY_TEST.md2
-rw-r--r--platform/android/tests/docs/CORE_TESTS.md21
-rw-r--r--platform/darwin/mbgl/storage/reachability.h (renamed from include/mbgl/platform/darwin/reachability.h)0
-rw-r--r--platform/darwin/mbgl/storage/reachability.m (renamed from platform/darwin/src/reachability.m)2
-rw-r--r--platform/darwin/resources/zh-Hans.lproj/Foundation.strings291
-rwxr-xr-xplatform/darwin/scripts/check-public-symbols.js83
-rw-r--r--platform/darwin/scripts/generate-style-code.js15
-rw-r--r--platform/darwin/src/MGLAccountManager.h3
-rw-r--r--platform/darwin/src/MGLAttributionInfo.h2
-rw-r--r--platform/darwin/src/MGLBackgroundStyleLayer.h2
-rw-r--r--platform/darwin/src/MGLBackgroundStyleLayer.mm3
-rw-r--r--platform/darwin/src/MGLCircleStyleLayer.h43
-rw-r--r--platform/darwin/src/MGLCircleStyleLayer.mm46
-rw-r--r--platform/darwin/src/MGLClockDirectionFormatter.h3
-rw-r--r--platform/darwin/src/MGLCompassDirectionFormatter.h3
-rw-r--r--platform/darwin/src/MGLCoordinateFormatter.h3
-rw-r--r--platform/darwin/src/MGLFeature.h8
-rw-r--r--platform/darwin/src/MGLFeature_Private.h2
-rw-r--r--platform/darwin/src/MGLFillStyleLayer.h2
-rw-r--r--platform/darwin/src/MGLFillStyleLayer.mm4
-rw-r--r--platform/darwin/src/MGLForegroundStyleLayer.h2
-rw-r--r--platform/darwin/src/MGLFoundation.h5
-rw-r--r--platform/darwin/src/MGLGeometry.h4
-rw-r--r--platform/darwin/src/MGLGeometry.mm8
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.h2
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.mm4
-rw-r--r--platform/darwin/src/MGLMapCamera.h3
-rw-r--r--platform/darwin/src/MGLMultiPoint.h2
-rw-r--r--platform/darwin/src/MGLOfflinePack.h2
-rw-r--r--platform/darwin/src/MGLOfflineStorage.h24
-rw-r--r--platform/darwin/src/MGLOpenGLStyleLayer.h3
-rw-r--r--platform/darwin/src/MGLOpenGLStyleLayer.mm2
-rw-r--r--platform/darwin/src/MGLPointAnnotation.h2
-rw-r--r--platform/darwin/src/MGLPointCollection.h2
-rw-r--r--platform/darwin/src/MGLPolygon.h3
-rw-r--r--platform/darwin/src/MGLPolyline.h3
-rw-r--r--platform/darwin/src/MGLRasterSource.h8
-rw-r--r--platform/darwin/src/MGLRasterSource.mm2
-rw-r--r--platform/darwin/src/MGLRasterStyleLayer.h2
-rw-r--r--platform/darwin/src/MGLRasterStyleLayer.mm3
-rw-r--r--platform/darwin/src/MGLShape.h2
-rw-r--r--platform/darwin/src/MGLShapeCollection.h2
-rw-r--r--platform/darwin/src/MGLShapeSource.h14
-rw-r--r--platform/darwin/src/MGLShapeSource.mm2
-rw-r--r--platform/darwin/src/MGLShapeSource_Private.h3
-rw-r--r--platform/darwin/src/MGLSource.h3
-rw-r--r--platform/darwin/src/MGLStyle.h4
-rw-r--r--platform/darwin/src/MGLStyle.mm8
-rw-r--r--platform/darwin/src/MGLStyleLayer.h2
-rw-r--r--platform/darwin/src/MGLStyleLayer.h.ejs2
-rw-r--r--platform/darwin/src/MGLStyleLayer.mm.ejs6
-rw-r--r--platform/darwin/src/MGLStyleLayer_Private.h1
-rw-r--r--platform/darwin/src/MGLStyleValue.h5
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.h2
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.mm4
-rw-r--r--platform/darwin/src/MGLTilePyramidOfflineRegion.h2
-rw-r--r--platform/darwin/src/MGLTileSource.h16
-rw-r--r--platform/darwin/src/MGLTileSource_Private.h6
-rw-r--r--platform/darwin/src/MGLTypes.h4
-rw-r--r--platform/darwin/src/MGLVectorSource.h2
-rw-r--r--platform/darwin/src/MGLVectorSource.mm2
-rw-r--r--platform/darwin/src/MGLVectorStyleLayer.h2
-rw-r--r--platform/darwin/src/NSDate+MGLAdditions.h1
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.mm3
-rw-r--r--platform/darwin/src/headless_backend_cgl.cpp64
-rw-r--r--platform/darwin/src/headless_backend_eagl.mm44
-rw-r--r--platform/darwin/src/headless_display_cgl.cpp52
-rw-r--r--platform/darwin/src/image.mm22
-rw-r--r--platform/darwin/src/logging_nslog.mm (renamed from platform/darwin/src/log_nslog.mm)2
-rw-r--r--platform/darwin/src/nsthread.mm2
-rw-r--r--platform/darwin/src/string_nsstring.mm2
-rw-r--r--platform/darwin/test/MGLBackgroundStyleLayerTests.mm2
-rw-r--r--platform/darwin/test/MGLCircleStyleLayerTests.mm107
-rw-r--r--platform/darwin/test/MGLFeatureTests.mm2
-rw-r--r--platform/darwin/test/MGLFillStyleLayerTests.mm4
-rw-r--r--platform/darwin/test/MGLLineStyleLayerTests.mm2
-rw-r--r--platform/darwin/test/MGLSymbolStyleLayerTests.mm8
-rw-r--r--platform/darwin/test/MGLVersionNumber.m15
-rw-r--r--platform/default/bidi.cpp127
-rw-r--r--platform/default/default_file_source.cpp2
-rw-r--r--platform/default/headless_backend_glx.cpp67
-rw-r--r--platform/default/headless_backend_osmesa.cpp65
-rw-r--r--platform/default/http_file_source.cpp2
-rw-r--r--platform/default/image.cpp12
-rw-r--r--platform/default/jpeg_reader.cpp2
-rw-r--r--platform/default/logging_stderr.cpp (renamed from platform/default/log_stderr.cpp)2
-rw-r--r--platform/default/mbgl/gl/headless_backend.cpp (renamed from platform/default/headless_backend.cpp)28
-rw-r--r--platform/default/mbgl/gl/headless_backend.hpp (renamed from include/mbgl/platform/default/headless_backend.hpp)60
-rw-r--r--platform/default/mbgl/gl/headless_display.cpp15
-rw-r--r--platform/default/mbgl/gl/headless_display.hpp20
-rw-r--r--platform/default/mbgl/gl/offscreen_view.cpp30
-rw-r--r--platform/default/mbgl/gl/offscreen_view.hpp (renamed from include/mbgl/platform/default/offscreen_view.hpp)6
-rw-r--r--platform/default/mbgl/storage/offline_database.cpp2
-rw-r--r--platform/default/mbgl/storage/offline_download.cpp2
-rw-r--r--platform/default/mbgl/util/default_styles.cpp (renamed from src/mbgl/util/default_styles.cpp)0
-rw-r--r--platform/default/mbgl/util/default_styles.hpp (renamed from include/mbgl/util/default_styles.hpp)0
-rw-r--r--platform/default/mbgl/util/default_thread_pool.cpp (renamed from platform/default/thread_pool.cpp)2
-rw-r--r--platform/default/mbgl/util/default_thread_pool.hpp (renamed from include/mbgl/platform/default/thread_pool.hpp)0
-rw-r--r--platform/default/offscreen_view.cpp47
-rw-r--r--platform/default/online_file_source.cpp2
-rw-r--r--platform/default/png_reader.cpp4
-rw-r--r--platform/default/sqlite3.cpp2
-rw-r--r--platform/default/string_stdlib.cpp4
-rw-r--r--platform/default/thread.cpp4
-rw-r--r--platform/default/webp_reader.cpp6
-rw-r--r--platform/glfw/glfw_view.cpp (renamed from platform/default/glfw_view.cpp)32
-rw-r--r--platform/glfw/glfw_view.hpp (renamed from include/mbgl/platform/default/glfw_view.hpp)7
-rw-r--r--platform/glfw/main.cpp (renamed from bin/glfw.cpp)12
-rw-r--r--platform/glfw/settings_json.cpp (renamed from platform/default/settings_json.cpp)2
-rw-r--r--platform/glfw/settings_json.hpp (renamed from include/mbgl/platform/default/settings_json.hpp)0
-rw-r--r--platform/ios/CHANGELOG.md8
-rw-r--r--platform/ios/DEVELOPING.md1
-rw-r--r--platform/ios/bitrise.yml31
-rw-r--r--platform/ios/config.cmake29
-rw-r--r--platform/ios/framework/Settings.bundle/zh-Hans.lproj/Root.strings3
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj25
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme2
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme2
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic+static.xcscheme2
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme2
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme2
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme2
-rw-r--r--platform/ios/resources/zh-Hans.lproj/Localizable.strings84
-rwxr-xr-xplatform/ios/scripts/metrics.sh20
-rw-r--r--platform/ios/src/MGLMapView.mm40
-rw-r--r--platform/ios/src/MGLMapboxEvents.m2
-rw-r--r--platform/ios/src/Mapbox.h6
-rw-r--r--platform/ios/src/UIImage+MGLAdditions.mm2
-rw-r--r--platform/ios/test/MGLSourceTests.m24
-rw-r--r--platform/ios/toolchain.cmake7
m---------platform/ios/uitest/KIF0
m---------platform/ios/uitest/OHHTTPStubs0
-rw-r--r--platform/linux/README.md6
-rw-r--r--platform/linux/config.cmake77
-rwxr-xr-xplatform/linux/scripts/after_success.sh10
-rwxr-xr-xplatform/linux/scripts/metrics.sh12
-rw-r--r--platform/linux/src/headless_backend_egl.cpp103
-rw-r--r--platform/linux/src/headless_backend_glx.cpp87
-rw-r--r--platform/linux/src/headless_display_egl.cpp69
-rw-r--r--platform/linux/src/headless_display_glx.cpp (renamed from platform/default/headless_display.cpp)57
-rw-r--r--platform/macos/CHANGELOG.md7
-rw-r--r--platform/macos/DEVELOPING.md1
-rw-r--r--platform/macos/bitrise.yml30
-rw-r--r--platform/macos/config.cmake43
-rw-r--r--platform/macos/macos.xcodeproj/project.pbxproj32
-rw-r--r--platform/macos/macos.xcodeproj/xcshareddata/xcschemes/CI.xcscheme2
-rw-r--r--platform/macos/macos.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme2
-rw-r--r--platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme2
-rw-r--r--platform/macos/scripts/executable.xcscheme8
-rw-r--r--platform/macos/scripts/library.xcscheme2
-rwxr-xr-xplatform/macos/scripts/metrics.sh7
-rw-r--r--platform/macos/scripts/node.xcscheme5
-rwxr-xr-xplatform/macos/scripts/package.sh3
-rw-r--r--platform/macos/sdk/zh-Hans.lproj/Localizable.strings15
-rw-r--r--platform/macos/src/MGLAnnotationImage.h3
-rw-r--r--platform/macos/src/MGLAttributionButton.h2
-rw-r--r--platform/macos/src/MGLMapView.h3
-rw-r--r--platform/macos/src/MGLMapView.mm47
-rw-r--r--platform/macos/src/MGLOpenGLLayer.mm2
-rw-r--r--platform/macos/src/Mapbox.h6
-rw-r--r--platform/macos/src/NSImage+MGLAdditions.mm4
-rw-r--r--platform/node/CHANGELOG.md22
-rw-r--r--platform/node/bitrise.yml3
-rwxr-xr-xplatform/node/scripts/after_script.sh19
-rwxr-xr-xplatform/node/scripts/after_success.sh13
-rw-r--r--platform/node/src/node_conversion.hpp2
-rw-r--r--platform/node/src/node_logging.cpp (renamed from platform/node/src/node_log.cpp)2
-rw-r--r--platform/node/src/node_logging.hpp (renamed from platform/node/src/node_log.hpp)2
-rw-r--r--platform/node/src/node_map.cpp160
-rw-r--r--platform/node/src/node_map.hpp8
-rw-r--r--platform/node/src/node_mapbox_gl_native.cpp2
-rw-r--r--platform/node/test/fixtures/zoom-center/expected.pngbin0 -> 882 bytes
-rw-r--r--platform/node/test/js/map.test.js204
-rw-r--r--platform/node/test/query.test.js2
-rw-r--r--platform/node/test/render.test.js2
-rw-r--r--platform/node/test/suite_implementation.js44
-rw-r--r--platform/qt/app/mapwindow.cpp211
-rw-r--r--platform/qt/app/mapwindow.hpp26
-rw-r--r--platform/qt/config.cmake25
-rw-r--r--platform/qt/config.qdocconf1
-rw-r--r--platform/qt/include/qmapbox.hpp34
-rw-r--r--platform/qt/include/qmapboxgl.hpp67
-rw-r--r--platform/qt/qmlapp/main.qml46
-rw-r--r--platform/qt/qt.cmake18
-rw-r--r--platform/qt/resources/common.qrc3
-rw-r--r--platform/qt/resources/source1.geojson (renamed from platform/qt/resources/source.geojson)0
-rw-r--r--platform/qt/resources/source2.geojson92
-rwxr-xr-xplatform/qt/scripts/toolchain.sh21
-rw-r--r--platform/qt/src/bidi.cpp52
-rw-r--r--platform/qt/src/http_file_source.cpp2
-rw-r--r--platform/qt/src/image.cpp4
-rw-r--r--platform/qt/src/qmapbox.cpp18
-rw-r--r--platform/qt/src/qmapboxgl.cpp1019
-rw-r--r--platform/qt/src/qmapboxgl_p.hpp9
-rw-r--r--platform/qt/src/qquickmapboxgl.cpp16
-rw-r--r--platform/qt/src/qquickmapboxgl.hpp3
-rw-r--r--platform/qt/src/qquickmapboxglrenderer.cpp4
-rw-r--r--platform/qt/src/qt_conversion.hpp4
-rw-r--r--platform/qt/src/run_loop_impl.hpp2
-rw-r--r--platform/qt/src/string_stdlib.cpp2
-rw-r--r--platform/qt/test/headless_backend_qt.cpp37
-rw-r--r--platform/qt/test/qmapboxgl.cpp26
-rwxr-xr-xscripts/build-shaders.js101
-rwxr-xr-xscripts/clang-tools.sh13
-rw-r--r--scripts/generate-style-code.js39
-rwxr-xr-xscripts/log_binary_size.sh42
-rwxr-xr-xscripts/publish_binary_size.sh75
-rw-r--r--scripts/style-code.js36
-rwxr-xr-xscripts/tidy.sh17
-rwxr-xr-xscripts/travis_setup.sh28
-rwxr-xr-xscripts/valgrind.sh6
-rw-r--r--scripts/valgrind.sup86
-rw-r--r--src/mbgl/algorithm/generate_clip_ids_impl.hpp11
-rw-r--r--src/mbgl/annotation/annotation_manager.cpp4
-rw-r--r--src/mbgl/annotation/annotation_tile.hpp2
-rw-r--r--src/mbgl/annotation/style_sourced_annotation_impl.cpp4
-rw-r--r--src/mbgl/geometry/feature_index.cpp11
-rw-r--r--src/mbgl/geometry/feature_index.hpp8
-rw-r--r--src/mbgl/geometry/line_atlas.cpp88
-rw-r--r--src/mbgl/geometry/line_atlas.hpp18
-rw-r--r--src/mbgl/gl/attribute.cpp29
-rw-r--r--src/mbgl/gl/attribute.hpp177
-rw-r--r--src/mbgl/gl/color_mode.cpp44
-rw-r--r--src/mbgl/gl/color_mode.hpp95
-rw-r--r--src/mbgl/gl/context.cpp404
-rw-r--r--src/mbgl/gl/context.hpp153
-rw-r--r--src/mbgl/gl/debugging.cpp4
-rw-r--r--src/mbgl/gl/depth_mode.cpp18
-rw-r--r--src/mbgl/gl/depth_mode.hpp36
-rw-r--r--src/mbgl/gl/draw_mode.hpp76
-rw-r--r--src/mbgl/gl/extension.cpp21
-rw-r--r--src/mbgl/gl/framebuffer.hpp5
-rw-r--r--src/mbgl/gl/index_buffer.hpp39
-rw-r--r--src/mbgl/gl/primitives.hpp22
-rw-r--r--src/mbgl/gl/program.hpp70
-rw-r--r--src/mbgl/gl/renderbuffer.hpp5
-rw-r--r--src/mbgl/gl/segment.hpp39
-rw-r--r--src/mbgl/gl/shader.cpp113
-rw-r--r--src/mbgl/gl/shader.hpp45
-rw-r--r--src/mbgl/gl/stencil_mode.cpp27
-rw-r--r--src/mbgl/gl/stencil_mode.hpp66
-rw-r--r--src/mbgl/gl/texture.hpp7
-rw-r--r--src/mbgl/gl/types.hpp97
-rw-r--r--src/mbgl/gl/uniform.cpp54
-rw-r--r--src/mbgl/gl/uniform.hpp94
-rw-r--r--src/mbgl/gl/value.cpp103
-rw-r--r--src/mbgl/gl/value.hpp129
-rw-r--r--src/mbgl/gl/vao.cpp58
-rw-r--r--src/mbgl/gl/vao.hpp78
-rw-r--r--src/mbgl/gl/vertex_buffer.hpp31
-rw-r--r--src/mbgl/layout/merge_lines.cpp4
-rw-r--r--src/mbgl/layout/symbol_feature.hpp3
-rw-r--r--src/mbgl/layout/symbol_instance.cpp2
-rw-r--r--src/mbgl/layout/symbol_instance.hpp7
-rw-r--r--src/mbgl/layout/symbol_layout.cpp345
-rw-r--r--src/mbgl/layout/symbol_layout.hpp21
-rw-r--r--src/mbgl/map/map.cpp242
-rw-r--r--src/mbgl/map/transform.cpp37
-rw-r--r--src/mbgl/map/transform.hpp2
-rw-r--r--src/mbgl/map/transform_state.cpp79
-rw-r--r--src/mbgl/map/transform_state.hpp15
-rw-r--r--src/mbgl/map/update.hpp3
-rw-r--r--src/mbgl/math/log2.cpp (renamed from src/mbgl/util/math.cpp)12
-rw-r--r--src/mbgl/programs/attributes.hpp23
-rw-r--r--src/mbgl/programs/circle_program.cpp7
-rw-r--r--src/mbgl/programs/circle_program.hpp59
-rw-r--r--src/mbgl/programs/collision_box_program.cpp7
-rw-r--r--src/mbgl/programs/collision_box_program.hpp56
-rw-r--r--src/mbgl/programs/debug_program.hpp27
-rw-r--r--src/mbgl/programs/fill_program.cpp47
-rw-r--r--src/mbgl/programs/fill_program.hpp123
-rw-r--r--src/mbgl/programs/line_program.cpp125
-rw-r--r--src/mbgl/programs/line_program.hpp177
-rw-r--r--src/mbgl/programs/program.hpp43
-rw-r--r--src/mbgl/programs/program_parameters.hpp16
-rw-r--r--src/mbgl/programs/programs.hpp50
-rw-r--r--src/mbgl/programs/raster_program.cpp7
-rw-r--r--src/mbgl/programs/raster_program.hpp67
-rw-r--r--src/mbgl/programs/symbol_program.cpp145
-rw-r--r--src/mbgl/programs/symbol_program.hpp136
-rw-r--r--src/mbgl/programs/uniforms.hpp33
-rw-r--r--src/mbgl/renderer/bucket.hpp5
-rw-r--r--src/mbgl/renderer/circle_bucket.cpp75
-rw-r--r--src/mbgl/renderer/circle_bucket.hpp20
-rw-r--r--src/mbgl/renderer/debug_bucket.cpp65
-rw-r--r--src/mbgl/renderer/debug_bucket.hpp14
-rw-r--r--src/mbgl/renderer/element_group.hpp28
-rw-r--r--src/mbgl/renderer/fill_bucket.cpp126
-rw-r--r--src/mbgl/renderer/fill_bucket.hpp35
-rw-r--r--src/mbgl/renderer/frame_history.cpp72
-rw-r--r--src/mbgl/renderer/frame_history.hpp18
-rw-r--r--src/mbgl/renderer/line_bucket.cpp118
-rw-r--r--src/mbgl/renderer/line_bucket.hpp33
-rw-r--r--src/mbgl/renderer/paint_parameters.hpp4
-rw-r--r--src/mbgl/renderer/painter.cpp193
-rw-r--r--src/mbgl/renderer/painter.hpp80
-rw-r--r--src/mbgl/renderer/painter_background.cpp112
-rw-r--r--src/mbgl/renderer/painter_circle.cpp78
-rw-r--r--src/mbgl/renderer/painter_clipping.cpp68
-rw-r--r--src/mbgl/renderer/painter_debug.cpp198
-rw-r--r--src/mbgl/renderer/painter_fill.cpp263
-rw-r--r--src/mbgl/renderer/painter_line.cpp195
-rw-r--r--src/mbgl/renderer/painter_raster.cpp92
-rw-r--r--src/mbgl/renderer/painter_symbol.cpp305
-rw-r--r--src/mbgl/renderer/raster_bucket.cpp23
-rw-r--r--src/mbgl/renderer/raster_bucket.hpp17
-rw-r--r--src/mbgl/renderer/render_tile.hpp1
-rw-r--r--src/mbgl/renderer/symbol_bucket.cpp76
-rw-r--r--src/mbgl/renderer/symbol_bucket.hpp48
-rw-r--r--src/mbgl/shader/circle_shader.cpp15
-rw-r--r--src/mbgl/shader/circle_shader.hpp30
-rw-r--r--src/mbgl/shader/circle_vertex.cpp7
-rw-r--r--src/mbgl/shader/circle_vertex.hpp39
-rw-r--r--src/mbgl/shader/collision_box_shader.cpp15
-rw-r--r--src/mbgl/shader/collision_box_shader.hpp27
-rw-r--r--src/mbgl/shader/collision_box_vertex.cpp7
-rw-r--r--src/mbgl/shader/collision_box_vertex.hpp43
-rw-r--r--src/mbgl/shader/fill_outline_pattern_shader.cpp15
-rw-r--r--src/mbgl/shader/fill_outline_pattern_shader.hpp37
-rw-r--r--src/mbgl/shader/fill_outline_shader.cpp15
-rw-r--r--src/mbgl/shader/fill_outline_shader.hpp26
-rw-r--r--src/mbgl/shader/fill_pattern_shader.cpp15
-rw-r--r--src/mbgl/shader/fill_pattern_shader.hpp36
-rw-r--r--src/mbgl/shader/fill_shader.cpp15
-rw-r--r--src/mbgl/shader/fill_shader.hpp25
-rw-r--r--src/mbgl/shader/fill_vertex.cpp7
-rw-r--r--src/mbgl/shader/fill_vertex.hpp30
-rw-r--r--src/mbgl/shader/line_pattern_shader.cpp15
-rw-r--r--src/mbgl/shader/line_pattern_shader.hpp41
-rw-r--r--src/mbgl/shader/line_sdf_shader.cpp15
-rw-r--r--src/mbgl/shader/line_sdf_shader.hpp42
-rw-r--r--src/mbgl/shader/line_shader.cpp15
-rw-r--r--src/mbgl/shader/line_shader.hpp35
-rw-r--r--src/mbgl/shader/line_vertex.cpp7
-rw-r--r--src/mbgl/shader/line_vertex.hpp72
-rw-r--r--src/mbgl/shader/raster_shader.cpp15
-rw-r--r--src/mbgl/shader/raster_shader.hpp35
-rw-r--r--src/mbgl/shader/raster_vertex.cpp7
-rw-r--r--src/mbgl/shader/raster_vertex.hpp39
-rw-r--r--src/mbgl/shader/shaders.hpp58
-rw-r--r--src/mbgl/shader/symbol_icon_shader.cpp15
-rw-r--r--src/mbgl/shader/symbol_icon_shader.hpp32
-rw-r--r--src/mbgl/shader/symbol_sdf_shader.cpp15
-rw-r--r--src/mbgl/shader/symbol_sdf_shader.hpp40
-rw-r--r--src/mbgl/shader/symbol_vertex.cpp9
-rw-r--r--src/mbgl/shader/symbol_vertex.hpp54
-rw-r--r--src/mbgl/sprite/sprite_atlas.cpp139
-rw-r--r--src/mbgl/sprite/sprite_atlas.hpp39
-rw-r--r--src/mbgl/sprite/sprite_image.cpp2
-rw-r--r--src/mbgl/sprite/sprite_parser.cpp27
-rw-r--r--src/mbgl/sprite/sprite_parser.hpp8
-rw-r--r--src/mbgl/style/bucket_parameters.cpp3
-rw-r--r--src/mbgl/style/bucket_parameters.hpp33
-rw-r--r--src/mbgl/style/class_dictionary.hpp1
-rw-r--r--src/mbgl/style/conversion/stringify.hpp256
-rw-r--r--src/mbgl/style/cross_faded_property_evaluator.cpp53
-rw-r--r--src/mbgl/style/cross_faded_property_evaluator.hpp48
-rw-r--r--src/mbgl/style/function.cpp81
-rw-r--r--src/mbgl/style/group_by_layout.cpp50
-rw-r--r--src/mbgl/style/group_by_layout.hpp14
-rw-r--r--src/mbgl/style/layer_impl.cpp6
-rw-r--r--src/mbgl/style/layer_impl.hpp19
-rw-r--r--src/mbgl/style/layers/background_layer.cpp17
-rw-r--r--src/mbgl/style/layers/background_layer_impl.cpp10
-rw-r--r--src/mbgl/style/layers/background_layer_impl.hpp5
-rw-r--r--src/mbgl/style/layers/background_layer_properties.cpp16
-rw-r--r--src/mbgl/style/layers/background_layer_properties.hpp23
-rw-r--r--src/mbgl/style/layers/circle_layer.cpp78
-rw-r--r--src/mbgl/style/layers/circle_layer_impl.cpp23
-rw-r--r--src/mbgl/style/layers/circle_layer_impl.hpp5
-rw-r--r--src/mbgl/style/layers/circle_layer_properties.cpp24
-rw-r--r--src/mbgl/style/layers/circle_layer_properties.hpp66
-rw-r--r--src/mbgl/style/layers/custom_layer_impl.cpp13
-rw-r--r--src/mbgl/style/layers/custom_layer_impl.hpp5
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer.cpp174
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer_impl.cpp19
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer_impl.hpp25
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer_properties.cpp9
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer_properties.hpp51
-rw-r--r--src/mbgl/style/layers/fill_layer.cpp33
-rw-r--r--src/mbgl/style/layers/fill_layer_impl.cpp21
-rw-r--r--src/mbgl/style/layers/fill_layer_impl.hpp5
-rw-r--r--src/mbgl/style/layers/fill_layer_properties.cpp24
-rw-r--r--src/mbgl/style/layers/fill_layer_properties.hpp51
-rw-r--r--src/mbgl/style/layers/layer.cpp.ejs25
-rw-r--r--src/mbgl/style/layers/layer_properties.cpp.ejs26
-rw-r--r--src/mbgl/style/layers/layer_properties.hpp.ejs41
-rw-r--r--src/mbgl/style/layers/line_layer.cpp70
-rw-r--r--src/mbgl/style/layers/line_layer_impl.cpp37
-rw-r--r--src/mbgl/style/layers/line_layer_impl.hpp5
-rw-r--r--src/mbgl/style/layers/line_layer_properties.cpp37
-rw-r--r--src/mbgl/style/layers/line_layer_properties.hpp106
-rw-r--r--src/mbgl/style/layers/raster_layer.cpp33
-rw-r--r--src/mbgl/style/layers/raster_layer_impl.cpp10
-rw-r--r--src/mbgl/style/layers/raster_layer_impl.hpp5
-rw-r--r--src/mbgl/style/layers/raster_layer_properties.cpp24
-rw-r--r--src/mbgl/style/layers/raster_layer_properties.hpp51
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp266
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.cpp97
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.hpp41
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.cpp75
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp340
-rw-r--r--src/mbgl/style/layout_property.hpp64
-rw-r--r--src/mbgl/style/paint_property.hpp224
-rw-r--r--src/mbgl/style/parser.cpp2
-rw-r--r--src/mbgl/style/property_evaluation_parameters.hpp (renamed from src/mbgl/style/calculation_parameters.hpp)6
-rw-r--r--src/mbgl/style/property_evaluator.cpp152
-rw-r--r--src/mbgl/style/property_evaluator.hpp46
-rw-r--r--src/mbgl/style/property_parsing.hpp2
-rw-r--r--src/mbgl/style/source_impl.cpp38
-rw-r--r--src/mbgl/style/source_impl.hpp3
-rw-r--r--src/mbgl/style/sources/geojson_source_impl.cpp2
-rw-r--r--src/mbgl/style/style.cpp73
-rw-r--r--src/mbgl/style/style.hpp8
-rw-r--r--src/mbgl/text/bidi.hpp32
-rw-r--r--src/mbgl/text/collision_tile.cpp3
-rw-r--r--src/mbgl/text/collision_tile.hpp2
-rw-r--r--src/mbgl/text/get_anchors.cpp1
-rw-r--r--src/mbgl/text/glyph.cpp2
-rw-r--r--src/mbgl/text/glyph.hpp20
-rw-r--r--src/mbgl/text/glyph_atlas.cpp92
-rw-r--r--src/mbgl/text/glyph_atlas.hpp13
-rw-r--r--src/mbgl/text/glyph_set.cpp309
-rw-r--r--src/mbgl/text/glyph_set.hpp33
-rw-r--r--src/mbgl/text/quads.cpp30
-rw-r--r--src/mbgl/text/quads.hpp9
-rw-r--r--src/mbgl/text/shaping.cpp8
-rw-r--r--src/mbgl/text/shaping.hpp11
-rw-r--r--src/mbgl/tile/geometry_tile.cpp21
-rw-r--r--src/mbgl/tile/geometry_tile.hpp9
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp83
-rw-r--r--src/mbgl/tile/raster_tile_worker.cpp3
-rw-r--r--src/mbgl/tile/tile.cpp2
-rw-r--r--src/mbgl/tile/tile.hpp3
-rw-r--r--src/mbgl/util/color.cpp9
-rw-r--r--src/mbgl/util/event.cpp (renamed from src/mbgl/platform/event.cpp)2
-rw-r--r--src/mbgl/util/i18n.cpp357
-rw-r--r--src/mbgl/util/i18n.hpp24
-rw-r--r--src/mbgl/util/ignore.hpp23
-rw-r--r--src/mbgl/util/indexed_tuple.hpp47
-rw-r--r--src/mbgl/util/interpolate.hpp4
-rw-r--r--src/mbgl/util/logging.cpp (renamed from src/mbgl/platform/log.cpp)2
-rw-r--r--src/mbgl/util/mapbox.cpp241
-rw-r--r--src/mbgl/util/math.hpp6
-rw-r--r--src/mbgl/util/offscreen_texture.cpp23
-rw-r--r--src/mbgl/util/offscreen_texture.hpp6
-rw-r--r--src/mbgl/util/premultiply.cpp10
-rw-r--r--src/mbgl/util/stopwatch.cpp2
-rw-r--r--src/mbgl/util/stopwatch.hpp2
-rw-r--r--src/mbgl/util/thread.hpp2
-rw-r--r--src/mbgl/util/tile_cover.cpp4
-rw-r--r--src/mbgl/util/url.cpp135
-rw-r--r--src/mbgl/util/url.hpp42
-rw-r--r--src/mbgl/util/utf.hpp15
-rw-r--r--test/actor/actor.test.cpp2
-rw-r--r--test/actor/actor_ref.test.cpp2
-rw-r--r--test/algorithm/generate_clip_ids.test.cpp1
-rw-r--r--test/api/annotations.test.cpp102
-rw-r--r--test/api/api_misuse.test.cpp19
-rw-r--r--test/api/custom_layer.test.cpp12
-rw-r--r--test/api/query.test.cpp10
-rw-r--r--test/api/render_missing.test.cpp12
-rw-r--r--test/api/repeated_render.test.cpp28
-rw-r--r--test/fixtures/annotations/assets.zipbin481374 -> 0 bytes
-rw-r--r--test/fixtures/annotations/debug_empty/expected.pngbin0 -> 1238 bytes
-rw-r--r--test/fixtures/annotations/debug_sparse/expected.pngbin0 -> 2933 bytes
-rw-r--r--test/fixtures/api/assets.zipbin167696 -> 0 bytes
-rw-r--r--test/fixtures/storage/assets.zipbin1243 -> 0 bytes
-rw-r--r--test/fixtures/style_parser/stop-zoom-value.info.json1
-rw-r--r--test/gl/bucket.test.cpp41
-rw-r--r--test/gl/object.test.cpp40
-rw-r--r--test/map/map.test.cpp153
-rw-r--r--test/map/transform.test.cpp79
-rw-r--r--test/sprite/sprite_atlas.test.cpp110
-rw-r--r--test/sprite/sprite_image.test.cpp18
-rw-r--r--test/sprite/sprite_parser.test.cpp129
-rw-r--r--test/src/mbgl/test/conversion_stubs.hpp2
-rw-r--r--test/src/mbgl/test/fixture_log_observer.hpp2
-rw-r--r--test/src/mbgl/test/stub_tile_observer.hpp22
-rw-r--r--test/src/mbgl/test/util.cpp23
-rw-r--r--test/src/mbgl/test/util.hpp9
-rw-r--r--test/storage/asset_file_source.test.cpp4
-rw-r--r--test/storage/local_file_source.test.cpp2
-rw-r--r--test/storage/online_file_source.test.cpp10
-rw-r--r--test/style/conversion/function.test.cpp54
-rw-r--r--test/style/conversion/geojson_options.test.cpp14
-rw-r--r--test/style/conversion/stringify.test.cpp98
-rw-r--r--test/style/filter.test.cpp6
-rw-r--r--test/style/functions.test.cpp42
-rw-r--r--test/style/group_by_layout.test.cpp44
-rw-r--r--test/style/source.test.cpp6
-rw-r--r--test/text/glyph_atlas.test.cpp4
-rw-r--r--test/text/quads.test.cpp96
-rw-r--r--test/tile/geojson_tile.test.cpp72
-rw-r--r--test/tile/raster_tile.test.cpp2
-rw-r--r--test/tile/tile_coordinate.test.cpp3
-rw-r--r--test/tile/vector_tile.test.cpp37
-rw-r--r--test/util/http_timeout.test.cpp2
-rw-r--r--test/util/image.test.cpp18
-rw-r--r--test/util/mapbox.test.cpp7
-rw-r--r--test/util/memory.test.cpp24
-rw-r--r--test/util/merge_lines.test.cpp54
-rw-r--r--test/util/offscreen_texture.test.cpp38
-rw-r--r--test/util/text_conversions.test.cpp2
-rw-r--r--test/util/tile_cover.test.cpp4
-rw-r--r--test/util/url.test.cpp207
1043 files changed, 58224 insertions, 47024 deletions
diff --git a/.gitignore b/.gitignore
index ecd9b7ec57..873b80fae8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,3 +30,5 @@ xcuserdata
/platform/macos/macos.xcworkspace/xcshareddata/macos.xcscmblueprint
/platform/ios/ios.xcworkspace/xcshareddata/ios.xcscmblueprint
/documentation
+test/fixtures/api/assets.zip
+test/fixtures/storage/assets.zip
diff --git a/.gitmodules b/.gitmodules
index af156810c6..9a9f6c1ed1 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -12,3 +12,6 @@
[submodule "platform/ios/uitest/OHHTTPStubs"]
path = platform/ios/uitest/OHHTTPStubs
url = https://github.com/AliSoftware/OHHTTPStubs.git
+[submodule "mapbox-gl-js"]
+ path = mapbox-gl-js
+ url = git://github.com/mapbox/mapbox-gl-js.git
diff --git a/.mason b/.mason
-Subproject 4279f58787acba8286789f861cf7c3c4ce47d52
+Subproject 0742f24ad5c49b8806abb0023f4a4f531bb18db
diff --git a/.travis.yml b/.travis.yml
index 57f6e10abc..d36352c570 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,27 +2,48 @@ git:
submodules: false
# Save common build configurations as shortcuts, so we can reference them later.
+addons:
+ apt:
+ sources:
+ - &common_sources [ 'ubuntu-toolchain-r-test', 'george-edison55-precise-backports' ]
+ packages:
+ - &common_packages [ 'libllvm3.8v4', 'cmake', 'cmake-data' ]
+ - &clang38_packages [ 'clang-3.8', 'libstdc++-5-dev', 'libstdc++6' ]
+ - &gcc5_packages [ 'gcc-5', 'g++-5' ]
+ - &egl_packages [ 'libgles2-mesa-dev', 'libgbm-dev' ]
+ - &glfw_packages [ 'libxrandr-dev', 'libxcursor-dev', 'libxinerama-dev' ]
+
addons_shortcuts:
- addons_clang35: &clang35
+ addons_clang38: &clang38
apt:
- sources: [ 'ubuntu-toolchain-r-test', 'george-edison55-precise-backports' ]
- packages: [ 'clang-3.5', 'libstdc++-4.9-dev', 'libstdc++6', 'libllvm3.8v4', 'cmake', 'cmake-data',
- 'libxrandr-dev', 'libxcursor-dev', 'libxinerama-dev' ]
+ sources: *common_sources
+ packages:
+ - *common_packages
+ - *clang38_packages
+ - *egl_packages
+ - *glfw_packages
addons_gcc5: &gcc5
apt:
- sources: [ 'ubuntu-toolchain-r-test', 'george-edison55-precise-backports' ]
- packages: [ 'g++-5', 'gcc-5', 'libllvm3.8v4', 'cmake', 'cmake-data',
- 'libxrandr-dev', 'libxcursor-dev', 'libxinerama-dev' ]
+ sources: *common_sources
+ packages:
+ - *common_packages
+ - *gcc5_packages
+ - *egl_packages
+ - *glfw_packages
addons_qt4: &qt4
apt:
- sources: [ 'ubuntu-toolchain-r-test', 'george-edison55-precise-backports' ]
- packages: [ 'g++-5', 'gcc-5', 'libjemalloc-dev', 'cmake', 'cmake-data',
- 'mesa-utils', 'qt4-default' ]
+ sources: *common_sources
+ packages:
+ - *common_packages
+ - *gcc5_packages
+ - [ 'libjemalloc-dev', 'mesa-utils', 'qt4-default' ]
addons_qt5: &qt5
apt:
- sources: [ 'ubuntu-toolchain-r-test', 'george-edison55-precise-backports' ]
- packages: [ 'g++-5', 'gcc-5', 'cmake', 'cmake-data',
- 'mesa-utils', 'libc6-dbg', 'qt5-default', 'libqt5opengl5-dev', 'qtdeclarative5-dev', 'qtpositioning5-dev', 'qtlocation5-dev' ]
+ sources: *common_sources
+ packages:
+ - *common_packages
+ - *gcc5_packages
+ - [ 'mesa-utils', 'libc6-dbg', 'qt5-default', 'libqt5opengl5-dev', 'qtdeclarative5-dev', 'qtpositioning5-dev', 'qtlocation5-dev' ]
env:
global:
@@ -38,9 +59,7 @@ env:
install:
- source ./scripts/travis_helper.sh
- source ./scripts/travis_setup.sh
-before_script:
- ccache --zero-stats
- - cmake --version
script:
- make linux
- make benchmark
@@ -49,101 +68,147 @@ script:
after_script:
- ccache --show-stats
- ./platform/linux/scripts/after_script.sh ${TRAVIS_JOB_NUMBER}
+after_success:
+ - ./platform/linux/scripts/after_success.sh
matrix:
include:
- # Clang 3.5 - Debug - Node
+ # LLVM 3.8.0 - clang-{format,tidy}
+ - os: linux
+ sudo: false
+ dist: trusty
+ language: cpp
+ env: _CXX=c++ _CC=cc
+ compiler: "check"
+ script:
+ - git fetch origin master:refs/remotes/origin/master
+ - make check
+
+ # OSMesa - Node - Clang 3.8 - Debug
- os: linux
sudo: required
dist: trusty
language: node
- compiler: "node4-clang35-debug"
- env: _CXX=clang++-3.5 _CC=clang-3.5 WITH_OSMESA=1
- addons: *clang35
+ compiler: "osmesa-node4-clang38-debug"
+ env: BUILDTYPE=Debug _CXX=clang++-3.8 _CC=clang-3.8 WITH_OSMESA=1
+ addons: *clang38
+ script:
+ - nvm install 4
+ - nvm use 4
+ - make node
+ - make test-node
+ after_script:
+ - ccache --show-stats
+ - ./platform/node/scripts/after_script.sh ${TRAVIS_JOB_NUMBER}
+
+ # EGL - Node - Clang 3.8 - Debug
+ - os: linux
+ sudo: required
+ dist: trusty
+ language: node
+ compiler: "egl-node4-clang38-debug"
+ env: BUILDTYPE=Debug _CXX=clang++-3.8 _CC=clang-3.8 WITH_EGL=1
+ addons: *clang38
+ before_script:
+ - mapbox_start_xvfb
+ script:
+ - nvm install 4
+ - nvm use 4
+ - make node
+ - make test-node
+ after_script:
+ - ccache --show-stats
+ - ./platform/node/scripts/after_script.sh ${TRAVIS_JOB_NUMBER}
+
+ # GLX - Node - Clang 3.8 - Release
+ - os: linux
+ sudo: required
+ dist: trusty
+ language: node
+ compiler: "glx-node4-clang38-release"
+ env: BUILDTYPE=Release _CXX=clang++-3.8 _CC=clang-3.8
+ addons: *clang38
before_script:
- export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
- export PUBLISH=$([[ "${TRAVIS_TAG:-}" == "node-v${PACKAGE_JSON_VERSION}" ]] && echo true)
- - export BUILDTYPE=$([[ -n ${PUBLISH:-} ]] && echo "Release" || echo "Debug")
+ - mapbox_start_xvfb
script:
- nvm install 4
- nvm use 4
- make node
- - if [[ -z ${PUBLISH} ]]; then make test-node; fi
+ - make test-node
after_script:
- ccache --show-stats
- ./platform/node/scripts/after_script.sh ${TRAVIS_JOB_NUMBER}
+ after_success:
+ - ./platform/node/scripts/after_success.sh
- # GCC 5 - Debug - Coverage
+ # OSMesa - GCC 5 - Debug (Coverage)
# FIXME: https://github.com/mapbox/mapbox-gl-native/issues/6918
- os: linux
sudo: required
dist: trusty
language: cpp
- compiler: "glfw-gcc5-debug"
+ compiler: "osmesa-gcc5-debug"
env: BUILDTYPE=Debug _CXX=g++-5 _CC=gcc-5 WITH_COVERAGE=1 WITH_OSMESA=1
addons: *gcc5
after_script:
- ccache --show-stats
- ./platform/linux/scripts/coveralls.sh
- # GCC 5 - Release
+ # OSMesa - GCC 5 - Release
- os: linux
sudo: required
dist: trusty
language: cpp
- compiler: "glfw-gcc5-release"
+ compiler: "osmesa-gcc5-release"
env: BUILDTYPE=Release _CXX=g++-5 _CC=gcc-5 WITH_OSMESA=1
addons: *gcc5
- # Clang 3.5 - Debug
- - os: linux
- sudo: required
- dist: trusty
- language: cpp
- compiler: "glfw-clang35-debug"
- env: BUILDTYPE=Debug _CXX=clang++-3.5 _CC=clang-3.5 WITH_OSMESA=1
- addons: *clang35
-
- # Clang 3.5 - Release
+ # OSMesa - Clang 3.8 - Debug
- os: linux
sudo: required
dist: trusty
language: cpp
- compiler: "glfw-clang35-release"
- env: BUILDTYPE=Release _CXX=clang++-3.5 _CC=clang-3.5 WITH_OSMESA=1
- addons: *clang35
+ compiler: "osmesa-clang38-debug"
+ env: BUILDTYPE=Debug _CXX=clang++-3.8 _CC=clang-3.8 WITH_OSMESA=1
+ addons: *clang38
- # Clang 3.5 - tidy
+ # OSMesa - Clang 3.8 - Release
- os: linux
sudo: required
dist: trusty
language: cpp
- compiler: "check-clang35-release"
- env: BUILDTYPE=Release _CXX=clang++-3.5 _CC=clang-3.5 WITH_OSMESA=1
- addons: *clang35
- script:
- - git fetch origin master:refs/remotes/origin/master
+ compiler: "osmesa-clang38-release"
+ env: BUILDTYPE=Release _CXX=clang++-3.8 _CC=clang-3.8 WITH_OSMESA=1
+ addons: *clang38
- # Qt 4 - Release
+ # Qt 4 - GCC 5 - Release
- os: linux
sudo: required
dist: trusty
language: cpp
compiler: "qt4-gcc5-release"
- env: BUILDTYPE=Release _CXX=g++-5 _CC=gcc-5 RUN_XVFB=1 WITH_QT_4=1
+ env: BUILDTYPE=Release _CXX=g++-5 _CC=gcc-5 WITH_QT_4=1
addons: *qt4
+ before_script:
+ - mapbox_start_xvfb
+ - mapbox_export_mesa_library_path
script:
- make qt-app
- LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so make run-qt-test-Memory.*:*.Load
- # Qt 5 - Release
+ # Qt 5 - GCC 5 - Release
- os: linux
sudo: required
dist: trusty
language: cpp
compiler: "qt5-gcc5-release"
- env: BUILDTYPE=Release _CXX=g++-5 _CC=gcc-5 RUN_XVFB=1
+ env: BUILDTYPE=Release _CXX=g++-5 _CC=gcc-5
addons: *qt5
+ before_script:
+ - mapbox_start_xvfb
+ - mapbox_export_mesa_library_path
script:
- make qt-app
- make qt-qml-app
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5e99f8031e..aa25cd6def 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,32 +10,65 @@ if(NOT EXISTS ".mason/mason.cmake")
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
endif()
+if(NOT EXISTS "mapbox-gl-js/package.json")
+ execute_process(
+ COMMAND git submodule update --init mapbox-gl-js
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
+ # Symlink mapbox-gl-js/node_modules so that the modules that are
+ # about to be installed get cached between CI runs.
+ execute_process(
+ COMMAND ln -s ../node_modules node_modules
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/mapbox-gl-js)
+ execute_process(
+ COMMAND npm install
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/mapbox-gl-js)
+endif()
+
include(.mason/mason.cmake)
option(WITH_CXX11ABI "Use cxx11abi mason packages" OFF)
option(WITH_COVERAGE "Enable coverage reports" OFF)
option(WITH_OSMESA "Use OSMesa headless backend" OFF)
+option(WITH_EGL "Use EGL backend" OFF)
+option(IS_CI_BUILD "Continuous integration build" OFF)
if(WITH_CXX11ABI)
set(MASON_CXXABI_SUFFIX -cxx11abi)
endif()
+if(WITH_OSMESA AND WITH_EGL)
+ message(FATAL_ERROR "WITH_OSMESA and WITH_EGL are mutually exclusive.")
+endif()
+
if(WITH_OSMESA)
- add_compile_options(-D__OSMESA__)
+ # Default mesa mason binary is OSMesa.
+ set(MASON_MESA_SUFFIX "")
+elseif(WITH_EGL)
+ add_definitions(-DMBGL_USE_GLES2=1)
+ set(MASON_MESA_SUFFIX "-egl")
+else()
+ set(MASON_MESA_SUFFIX "-glx")
endif()
-mason_use(geometry VERSION 0.8.0 HEADER_ONLY)
-mason_use(variant VERSION 1.1.0 HEADER_ONLY)
+if(IS_CI_BUILD)
+ add_compile_options(-DCI_BUILD=1)
+endif()
+
+mason_use(geometry VERSION 0.9.0 HEADER_ONLY)
+mason_use(variant VERSION 1.1.4 HEADER_ONLY)
mason_use(unique_resource VERSION dev HEADER_ONLY)
mason_use(rapidjson VERSION 1.1.0 HEADER_ONLY)
-mason_use(boost VERSION 1.60.0 HEADER_ONLY)
+mason_use(boost VERSION 1.62.0 HEADER_ONLY)
mason_use(geojsonvt VERSION 6.1.3 HEADER_ONLY)
mason_use(supercluster VERSION 0.2.0 HEADER_ONLY)
mason_use(kdbush VERSION 0.1.1 HEADER_ONLY)
mason_use(earcut VERSION 0.12.1 HEADER_ONLY)
mason_use(protozero VERSION 1.4.2 HEADER_ONLY)
mason_use(pixelmatch VERSION 0.10.0 HEADER_ONLY)
-mason_use(geojson VERSION 0.3.2 HEADER_ONLY)
+mason_use(geojson VERSION 0.4.0 HEADER_ONLY)
+mason_use(polylabel VERSION 1.0.2 HEADER_ONLY)
+
+add_definitions(-DRAPIDJSON_HAS_STDSTRING=1)
if(WITH_COVERAGE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
@@ -44,7 +77,7 @@ endif(WITH_COVERAGE)
set(CMAKE_CONFIGURATION_TYPES Debug Release)
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wextra -Wshadow -Werror -Wno-variadic-macros -Wno-unknown-pragmas")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -ftemplate-depth=1024 -Wall -Wextra -Wshadow -Werror -Wno-variadic-macros -Wno-unknown-pragmas")
if(APPLE)
# -Wno-error=unused-command-line-argument is required due to https://llvm.org/bugs/show_bug.cgi?id=7798
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unused-command-line-argument")
diff --git a/INSTALL.md b/INSTALL.md
index b7a383f1e6..0789f5e0af 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -28,7 +28,7 @@ targets.
- g++-5 or later
- [CMake](https://cmake.org/) 3.1 or later (for build only)
- [cURL](https://curl.haxx.se) (for build only)
- - [Node.js](https://nodejs.org/) (for build only)
+ - [Node.js](https://nodejs.org/) 4.2.1 or later (for build only)
- [`pkg-config`](https://wiki.freedesktop.org/www/Software/pkg-config/) (for build only)
Depending on your operating system and target, you'll need additional
diff --git a/Makefile b/Makefile
index 4f568114b7..c4e123d645 100644
--- a/Makefile
+++ b/Makefile
@@ -52,7 +52,7 @@ endif
.NOTPARALLEL: node_modules
node_modules: package.json
- npm update # Install dependencies but don't run our own install script.
+ npm install --ignore-scripts # Install dependencies but don't run our own install script.
BUILD_DEPS += .mason/mason
BUILD_DEPS += Makefile
@@ -192,8 +192,8 @@ compdb: $(BUILD_DEPS) $(TEST_DEPS) $(MACOS_COMPDB_PATH)/Makefile
.PHONY: clang-tools
clang-tools: compdb
- if test -z $(CLANG_TIDY); then .mason/mason install clang-tidy 3.8.0; fi
- if test -z $(CLANG_FORMAT); then .mason/mason install clang-format 3.8.0; fi
+ if test -z $(CLANG_TIDY); then .mason/mason install clang-tidy 3.9.1; fi
+ if test -z $(CLANG_FORMAT); then .mason/mason install clang-format 3.9.1; fi
$(MAKE) -C $(MACOS_COMPDB_PATH) mbgl-headers
.PHONY: tidy
@@ -277,12 +277,19 @@ ideploy:
idocument:
OUTPUT=$(OUTPUT) ./platform/ios/scripts/document.sh
-style-code-darwin:
+.PHONY: darwin-style-code
+darwin-style-code:
node platform/darwin/scripts/generate-style-code.js
node platform/darwin/scripts/update-examples.js
+style-code: darwin-style-code
+.PHONY: darwin-update-examples
darwin-update-examples:
node platform/darwin/scripts/update-examples.js
+
+.PHONY: check-public-symbols
+check-public-symbols:
+ node platform/darwin/scripts/check-public-symbols.js macOS
endif
#### Linux targets #####################################################
@@ -300,7 +307,9 @@ $(LINUX_BUILD): $(BUILD_DEPS)
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DWITH_CXX11ABI=$(shell scripts/check-cxx11abi.sh) \
-DWITH_COVERAGE=${WITH_COVERAGE} \
- -DWITH_OSMESA=${WITH_OSMESA})
+ -DIS_CI_BUILD=${CI} \
+ -DWITH_OSMESA=${WITH_OSMESA} \
+ -DWITH_EGL=${WITH_EGL})
.PHONY: linux
linux: glfw-app render offline
@@ -355,8 +364,8 @@ compdb: $(LINUX_BUILD)
.PHONY: clang-tools
clang-tools: compdb
- if test -z $(CLANG_TIDY); then .mason/mason install clang-tidy 3.8.0; fi
- if test -z $(CLANG_FORMAT); then .mason/mason install clang-format 3.8.0; fi
+ if test -z $(CLANG_TIDY); then .mason/mason install clang-tidy 3.9.1; fi
+ if test -z $(CLANG_FORMAT); then .mason/mason install clang-format 3.9.1; fi
$(NINJA) $(NINJA_ARGS) -j$(JOBS) -C $(LINUX_OUTPUT_PATH) mbgl-headers
.PHONY: tidy
@@ -393,9 +402,11 @@ $(QT_BUILD): $(BUILD_DEPS)
-DMASON_PLATFORM=$(BUILD_PLATFORM) \
-DMASON_PLATFORM_VERSION=$(BUILD_PLATFORM_VERSION) \
-DWITH_QT_DECODERS=${WITH_QT_DECODERS} \
+ -DWITH_QT_I18N=${WITH_QT_I18N} \
-DWITH_QT_4=${WITH_QT_4} \
-DWITH_CXX11ABI=$(shell scripts/check-cxx11abi.sh) \
- -DWITH_COVERAGE=${WITH_COVERAGE})
+ -DWITH_COVERAGE=${WITH_COVERAGE} \
+ -DIS_CI_BUILD=${CI})
ifeq ($(HOST_PLATFORM), macos)
@@ -407,9 +418,11 @@ $(MACOS_QT_PROJ_PATH): $(BUILD_DEPS)
-DMASON_PLATFORM=$(BUILD_PLATFORM) \
-DMASON_PLATFORM_VERSION=$(BUILD_PLATFORM_VERSION) \
-DWITH_QT_DECODERS=${WITH_QT_DECODERS} \
+ -DWITH_QT_I18N=${WITH_QT_I18N} \
-DWITH_QT_4=${WITH_QT_4} \
-DWITH_CXX11ABI=$(shell scripts/check-cxx11abi.sh) \
- -DWITH_COVERAGE=${WITH_COVERAGE})
+ -DWITH_COVERAGE=${WITH_COVERAGE} \
+ -DIS_CI_BUILD=${CI})
@# Create Xcode schemes so that we can use xcodebuild from the command line. CMake doesn't
@# create these automatically.
@@ -469,20 +482,26 @@ test-node: node
#### Android targets ###########################################################
-ANDROID_ENV = platform/android/scripts/toolchain.sh
-ANDROID_ABIS = arm-v5 arm-v7 arm-v8 x86 x86-64 mips
+MBGL_ANDROID_ENV = platform/android/scripts/toolchain.sh
+MBGL_ANDROID_ABIS = arm-v5 arm-v7 arm-v8 x86 x86-64 mips
+MBGL_ANDROID_LOCAL_WORK_DIR = /data/local/tmp/core-tests
+MBGL_ANDROID_LIBDIR = lib$(if $(filter arm-v8 x86-64,$1),64)
+MBGL_ANDROID_DALVIKVM = dalvikvm$(if $(filter arm-v8 x86-64,$1),64,32)
+MBGL_ANDROID_APK_SUFFIX = $(if $(filter Release,$(BUILDTYPE)),release-unsigned,debug)
+MBGL_ANDROID_CORE_TEST_DIR = build/android-$1/$(BUILDTYPE)/core-tests
-.PHONY: style-code-android
-style-code-android: $(BUILD_DEPS)
+.PHONY: android-style-code
+android-style-code:
node platform/android/scripts/generate-style-code.js
+style-code: android-style-code
define ANDROID_RULES
-build/android-$1/$(BUILDTYPE): style-code-android
+build/android-$1/$(BUILDTYPE): $(BUILD_DEPS)
mkdir -p build/android-$1/$(BUILDTYPE)
build/android-$1/$(BUILDTYPE)/toolchain.cmake: platform/android/scripts/toolchain.sh build/android-$1/$(BUILDTYPE)
- $(ANDROID_ENV) $1 > build/android-$1/$(BUILDTYPE)/toolchain.cmake
+ $(MBGL_ANDROID_ENV) $1 > build/android-$1/$(BUILDTYPE)/toolchain.cmake
build/android-$1/$(BUILDTYPE)/Makefile: build/android-$1/$(BUILDTYPE)/toolchain.cmake platform/android/config.cmake
cd build/android-$1/$(BUILDTYPE) && cmake ../../.. -G Ninja \
@@ -491,38 +510,120 @@ build/android-$1/$(BUILDTYPE)/Makefile: build/android-$1/$(BUILDTYPE)/toolchain.
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DMBGL_PLATFORM=android
+.PHONY: android-test-lib-$1
+android-test-lib-$1: build/android-$1/$(BUILDTYPE)/Makefile
+ $(NINJA) $(NINJA_ARGS) -j$(JOBS) -C build/android-$1/$(BUILDTYPE) mbgl-test
+
.PHONY: android-lib-$1
android-lib-$1: build/android-$1/$(BUILDTYPE)/Makefile
- $(NINJA) $(NINJA_ARGS) -j$(JOBS) -C build/android-$1/$(BUILDTYPE) all
+ $(NINJA) $(NINJA_ARGS) -j$(JOBS) -C build/android-$1/$(BUILDTYPE) mapbox-gl example-custom-layer
.PHONY: android-$1
android-$1: android-lib-$1
- cd platform/android && ./gradlew --parallel --max-workers=$(JOBS) assemble$(BUILDTYPE)
+ cd platform/android && ./gradlew --parallel --max-workers=$(JOBS) :MapboxGLAndroidSDKTestApp:assemble$(BUILDTYPE)
+
+.PHONY: android-core-test-$1
+android-core-test-$1: android-test-lib-$1
+ mkdir -p $(MBGL_ANDROID_CORE_TEST_DIR)
+
+ # Compile main sources and extract the classes (using the test app to get all transitive dependencies in one place)
+ cd platform/android && ./gradlew :MapboxGLAndroidSDKTestApp:assemble$(BUILDTYPE)
+ unzip -o platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-$(MBGL_ANDROID_APK_SUFFIX).apk classes.dex -d $(MBGL_ANDROID_CORE_TEST_DIR)
+
+ # Compile Test runner
+ find platform/android/src/test -name "*.java" > $(MBGL_ANDROID_CORE_TEST_DIR)/java-sources.txt
+ javac -sourcepath platform/android/src/test -d $(MBGL_ANDROID_CORE_TEST_DIR) -source 1.7 -target 1.7 @$(MBGL_ANDROID_CORE_TEST_DIR)/java-sources.txt
+
+ # Combine and dex
+ cd $(MBGL_ANDROID_CORE_TEST_DIR) && $(ANDROID_HOME)/build-tools/25.0.0/dx --dex --output=test.jar *.class classes.dex
+
+run-android-core-test-$1-%: android-core-test-$1
+ # Ensure clean state on the device
+ adb shell "rm -Rf $(MBGL_ANDROID_LOCAL_WORK_DIR) && mkdir -p $(MBGL_ANDROID_LOCAL_WORK_DIR)/test"
+
+ # Generate zipped asset files
+ cd test/fixtures/api && zip -r assets.zip assets && cd -
+ cd test/fixtures/storage && zip -r assets.zip assets && cd -
+
+ # Push all needed files to the device
+ adb push $(MBGL_ANDROID_CORE_TEST_DIR)/test.jar $(MBGL_ANDROID_LOCAL_WORK_DIR) > /dev/null 2>&1
+ adb push test/fixtures $(MBGL_ANDROID_LOCAL_WORK_DIR)/test > /dev/null 2>&1
+ adb push build/android-$1/$(BUILDTYPE)/stripped/libmapbox-gl.so $(MBGL_ANDROID_LOCAL_WORK_DIR) > /dev/null 2>&1
+ adb push build/android-$1/$(BUILDTYPE)/stripped/libmbgl-test.so $(MBGL_ANDROID_LOCAL_WORK_DIR) > /dev/null 2>&1
+
+ # Kick off the tests
+ adb shell "export LD_LIBRARY_PATH=/system/$(MBGL_ANDROID_LIBDIR):$(MBGL_ANDROID_LOCAL_WORK_DIR) && cd $(MBGL_ANDROID_LOCAL_WORK_DIR) && $(MBGL_ANDROID_DALVIKVM) -cp $(MBGL_ANDROID_LOCAL_WORK_DIR)/test.jar Main --gtest_filter=$$*"
+
+ # Gather the results and unpack them
+ adb shell "cd $(MBGL_ANDROID_LOCAL_WORK_DIR) && tar -cvzf results.tgz test/fixtures/* > /dev/null 2>&1"
+ adb pull $(MBGL_ANDROID_LOCAL_WORK_DIR)/results.tgz $(MBGL_ANDROID_CORE_TEST_DIR)/ > /dev/null 2>&1
+ rm -rf $(MBGL_ANDROID_CORE_TEST_DIR)/results && mkdir -p $(MBGL_ANDROID_CORE_TEST_DIR)/results
+ tar -xzf $(MBGL_ANDROID_CORE_TEST_DIR)/results.tgz --strip-components=2 -C $(MBGL_ANDROID_CORE_TEST_DIR)/results
+
+.PHONY: run-android-core-test-$1
+run-android-core-test-$1: run-android-core-test-$1-*
+
+.PHONY: run-android-$1
+run-android-$1: android-$1
+ cd platform/android && ./gradlew :MapboxGLAndroidSDKTestApp:install$(BUILDTYPE) && adb shell am start -n com.mapbox.mapboxsdk.testapp/.activity.FeatureOverviewActivity
apackage: android-lib-$1
endef
-$(foreach abi,$(ANDROID_ABIS),$(eval $(call ANDROID_RULES,$(abi))))
+$(foreach abi,$(MBGL_ANDROID_ABIS),$(eval $(call ANDROID_RULES,$(abi))))
.PHONY: android
android: android-arm-v7
-.PHONY: android-test
-android-test:
- cd platform/android && ./gradlew testDebugUnitTest --continue
+.PHONY: run-android
+run-android: run-android-arm-v7
+
+.PHONY: run-android-unit-test
+run-android-unit-test:
+ cd platform/android && ./gradlew :MapboxGLAndroidSDKTestApp:testDebugUnitTest --continue
+
+run-android-unit-test-%:
+ cd platform/android && ./gradlew :MapboxGLAndroidSDKTestApp:testDebugUnitTest --tests "$*"
+
+.PHONY: run-android-wear-unit-test
+run-android-wear-unit-test:
+ cd platform/android && ./gradlew :MapboxGLAndroidSDKWearTestApp:testDebugUnitTest --continue
+
+.PHONY: android-ui-test
+android-ui-test:
+ cd platform/android && ./gradlew :MapboxGLAndroidSDKTestApp:assembleDebug --continue && ./gradlew :MapboxGLAndroidSDKTestApp:assembleAndroidTest --continue
-.PHONY: android-test-apk
-android-test-apk:
- cd platform/android && ./gradlew assembleDebug --continue && ./gradlew assembleAndroidTest --continue
+.PHONY: run-android-ui-test
+run-android-ui-test:
+ cd platform/android && ./gradlew :MapboxGLAndroidSDKTestApp:connectedAndroidTest -i
+
+run-android-ui-test-%:
+ cd platform/android && ./gradlew :MapboxGLAndroidSDKTestApp:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class="$*"
+
+.PHONY: run-android-ui-test-aws
+run-android-ui-test-aws:
+ cd platform/android && ./gradlew devicefarmUpload
+
+.PHONY: run-android-ui-test-spoon
+run-android-ui-test-spoon:
+ cd platform/android && ./gradlew spoon
.PHONY: apackage
apackage:
- cd platform/android && ./gradlew --parallel-threads=$(JOBS) assemble$(BUILDTYPE)
+ cd platform/android && ./gradlew --parallel --max-workers=$(JOBS) assemble$(BUILDTYPE)
-.PHONY: android-generate-test
-android-generate-test:
+.PHONY: test-code-android
+test-code-android:
node platform/android/scripts/generate-test-code.js
+.PHONY: android-ndk-stack
+android-ndk-stack:
+ adb logcat | ndk-stack -sym build/android-arm-v7/Debug
+
+.PHONY: android-checkstyle
+android-checkstyle:
+ cd platform/android && ./gradlew checkstyle
+
#### Miscellaneous targets #####################################################
.PHONY: style-code
@@ -534,6 +635,8 @@ clean:
-rm -rf ./build \
./platform/android/MapboxGLAndroidSDK/build \
./platform/android/MapboxGLAndroidSDKTestApp/build \
+ ./platform/android/MapboxGLAndroidSDKWearTestApp/build \
+ ./platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen \
./platform/android/MapboxGLAndroidSDK/src/main/jniLibs \
./platform/android/MapboxGLAndroidSDKTestApp/src/main/jniLibs \
./platform/android/MapboxGLAndroidSDK/src/main/assets
diff --git a/benchmark/api/query.benchmark.cpp b/benchmark/api/query.benchmark.cpp
index 5a95cd7666..ba696876cd 100644
--- a/benchmark/api/query.benchmark.cpp
+++ b/benchmark/api/query.benchmark.cpp
@@ -2,9 +2,9 @@
#include <mbgl/benchmark/util.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/network_status.hpp>
@@ -34,10 +34,10 @@ public:
util::RunLoop loop;
HeadlessBackend backend;
- OffscreenView view{ backend.getContext(), {{ 1000, 1000 }} };
+ OffscreenView view{ backend.getContext(), { 1000, 1000 } };
DefaultFileSource fileSource{ "benchmark/fixtures/api/cache.db", "." };
ThreadPool threadPool{ 4 };
- Map map{ backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still };
+ Map map{ backend, view.size, 1, fileSource, threadPool, MapMode::Still };
ScreenBox box{{ 0, 0 }, { 1000, 1000 }};
};
diff --git a/benchmark/src/mbgl/benchmark/util.cpp b/benchmark/src/mbgl/benchmark/util.cpp
index 39c5f86883..87d68ea729 100644
--- a/benchmark/src/mbgl/benchmark/util.cpp
+++ b/benchmark/src/mbgl/benchmark/util.cpp
@@ -1,5 +1,5 @@
#include <mbgl/benchmark/util.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/map/view.hpp>
@@ -15,7 +15,7 @@ void render(Map& map, OffscreenView& view) {
result = view.readStillImage();
});
- while (!result.size()) {
+ while (!result.valid()) {
util::RunLoop::Get()->runOnce();
}
}
diff --git a/bin/render.cpp b/bin/render.cpp
index ad29d91993..d275b445d2 100644
--- a/bin/render.cpp
+++ b/bin/render.cpp
@@ -3,10 +3,11 @@
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
+#include <mbgl/util/url.hpp>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
@@ -27,8 +28,9 @@ int main(int argc, char *argv[]) {
double bearing = 0;
double pitch = 0;
- int width = 512;
- int height = 512;
+ uint32_t pixelRatio = 1;
+ uint32_t width = 512;
+ uint32_t height = 512;
static std::string output = "out.png";
std::string cache_file = "cache.sqlite";
std::string asset_root = ".";
@@ -46,6 +48,7 @@ int main(int argc, char *argv[]) {
("pitch,p", po::value(&pitch)->value_name("degrees")->default_value(pitch), "Pitch")
("width,w", po::value(&width)->value_name("pixels")->default_value(width), "Image width")
("height,h", po::value(&height)->value_name("pixels")->default_value(height), "Image height")
+ ("ratio,r", po::value(&pixelRatio)->value_name("number")->default_value(pixelRatio), "Image scale factor")
("class,c", po::value(&classes)->value_name("name"), "Class name")
("token,t", po::value(&token)->value_name("key")->default_value(token), "Mapbox access token")
("debug", po::bool_switch(&debug)->default_value(debug), "Debug mode")
@@ -63,8 +66,6 @@ int main(int argc, char *argv[]) {
exit(1);
}
- std::string style = mbgl::util::read_file(style_path);
-
using namespace mbgl;
util::RunLoop loop;
@@ -84,11 +85,16 @@ int main(int argc, char *argv[]) {
}
HeadlessBackend backend;
- OffscreenView view(backend.getContext(), {{ static_cast<uint16_t>(width), static_cast<uint16_t>(height) }});
+ OffscreenView view(backend.getContext(), { width * pixelRatio, height * pixelRatio });
ThreadPool threadPool(4);
- Map map(backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still);
+ Map map(backend, mbgl::Size { width, height }, pixelRatio, fileSource, threadPool, MapMode::Still);
+
+ if (util::isURL(style_path)) {
+ map.setStyleURL(style_path);
+ } else {
+ map.setStyleJSON(mbgl::util::read_file(style_path));
+ }
- map.setStyleJSON(style);
map.setClasses(classes);
map.setLatLngZoom({ lat, lon }, zoom);
diff --git a/cloudformation/travis.template b/cloudformation/travis.template
index b65093907c..e6b404d9a4 100644
--- a/cloudformation/travis.template
+++ b/cloudformation/travis.template
@@ -8,42 +8,6 @@
"Properties": {
"Policies": [
{
- "PolicyName": "list-testing-old",
- "PolicyDocument": {
- "Statement": [
- {
- "Action": [
- "s3:ListBucket"
- ],
- "Effect": "Allow",
- "Resource": [
- "arn:aws:s3:::mapbox-gl-testing"
- ]
- }
- ]
- }
- },
- {
- "PolicyName": "build-testing-old",
- "PolicyDocument": {
- "Statement": [
- {
- "Action": [
- "s3:DeleteObject",
- "s3:GetObject",
- "s3:GetObjectAcl",
- "s3:PutObject",
- "s3:PutObjectAcl"
- ],
- "Effect": "Allow",
- "Resource": [
- "arn:aws:s3:::mapbox-gl-testing/*"
- ]
- }
- ]
- }
- },
- {
"PolicyName": "list-testing",
"PolicyDocument": {
"Statement": [
@@ -113,7 +77,7 @@
"s3:PutObjectAcl"
],
"Resource": [
- "arn:aws:s3:::mapbox-node-binary/mapbox-gl-native/*"
+ "arn:aws:s3:::mapbox-node-binary/@mapbox/mapbox-gl-native/*"
],
"Effect": "Allow"
}
@@ -148,6 +112,24 @@
}
]
}
+ },
+ {
+ "PolicyName": "cloudwatch-metrics",
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "cloudwatch:PutMetricData",
+ "cloudwatch:GetMetricData",
+ "cloudwatch:GetMetricStatistics"
+ ],
+ "Effect": "Allow",
+ "Resource": [
+ "*"
+ ]
+ }
+ ]
+ }
}
]
}
@@ -179,6 +161,44 @@
}
]
}
+ },
+ {
+ "PolicyName": "publish-metrics",
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "s3:DeleteObject",
+ "s3:GetObject",
+ "s3:GetObjectAcl",
+ "s3:PutObject",
+ "s3:PutObjectAcl"
+ ],
+ "Effect": "Allow",
+ "Resource": [
+ "arn:aws:s3:::mapbox/mapbox-gl-native/metrics/*"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "PolicyName": "cloudwatch-metrics",
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "cloudwatch:PutMetricData",
+ "cloudwatch:GetMetricData",
+ "cloudwatch:GetMetricStatistics"
+ ],
+ "Effect": "Allow",
+ "Resource": [
+ "*"
+ ]
+ }
+ ]
+ }
}
]
}
diff --git a/cmake/benchmark.cmake b/cmake/benchmark.cmake
index 79da54459e..0752647a2d 100644
--- a/cmake/benchmark.cmake
+++ b/cmake/benchmark.cmake
@@ -14,12 +14,6 @@ target_include_directories(mbgl-benchmark
PRIVATE platform/default
)
-if(DEFINED ENV{CI})
- target_compile_definitions(mbgl-benchmark
- PRIVATE -DCI_BUILD=1
- )
-endif()
-
target_link_libraries(mbgl-benchmark
PRIVATE mbgl-core
)
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index 4d5cddbc49..6c44117cd8 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -54,12 +54,17 @@ set(MBGL_CORE_FILES
# gl
include/mbgl/gl/gl.hpp
- include/mbgl/gl/implementation.hpp
+ src/mbgl/gl/attribute.cpp
src/mbgl/gl/attribute.hpp
+ src/mbgl/gl/color_mode.cpp
+ src/mbgl/gl/color_mode.hpp
src/mbgl/gl/context.cpp
src/mbgl/gl/context.hpp
src/mbgl/gl/debugging.cpp
src/mbgl/gl/debugging.hpp
+ src/mbgl/gl/depth_mode.cpp
+ src/mbgl/gl/depth_mode.hpp
+ src/mbgl/gl/draw_mode.hpp
src/mbgl/gl/extension.cpp
src/mbgl/gl/extension.hpp
src/mbgl/gl/framebuffer.hpp
@@ -67,18 +72,19 @@ set(MBGL_CORE_FILES
src/mbgl/gl/index_buffer.hpp
src/mbgl/gl/object.cpp
src/mbgl/gl/object.hpp
+ src/mbgl/gl/primitives.hpp
+ src/mbgl/gl/program.hpp
src/mbgl/gl/renderbuffer.hpp
- src/mbgl/gl/shader.cpp
- src/mbgl/gl/shader.hpp
+ src/mbgl/gl/segment.hpp
src/mbgl/gl/state.hpp
+ src/mbgl/gl/stencil_mode.cpp
+ src/mbgl/gl/stencil_mode.hpp
src/mbgl/gl/texture.hpp
src/mbgl/gl/types.hpp
src/mbgl/gl/uniform.cpp
src/mbgl/gl/uniform.hpp
src/mbgl/gl/value.cpp
src/mbgl/gl/value.hpp
- src/mbgl/gl/vao.cpp
- src/mbgl/gl/vao.hpp
src/mbgl/gl/vertex_array.cpp
src/mbgl/gl/vertex_array.hpp
src/mbgl/gl/vertex_buffer.hpp
@@ -112,33 +118,34 @@ set(MBGL_CORE_FILES
# math
include/mbgl/math/clamp.hpp
+ include/mbgl/math/log2.hpp
include/mbgl/math/minmax.hpp
include/mbgl/math/wrap.hpp
-
- # mbgl
- include/mbgl/mbgl.hpp
+ src/mbgl/math/log2.cpp
# parsedate
src/parsedate/parsedate.c
src/parsedate/parsedate.h
- # platform
- include/mbgl/platform/event.hpp
- include/mbgl/platform/log.hpp
- include/mbgl/platform/platform.hpp
- src/mbgl/platform/event.cpp
- src/mbgl/platform/log.cpp
-
- # platform/darwin
- include/mbgl/platform/darwin/reachability.h
-
- # platform/default
- include/mbgl/platform/default/glfw_view.hpp
- include/mbgl/platform/default/headless_backend.hpp
- include/mbgl/platform/default/headless_display.hpp
- include/mbgl/platform/default/offscreen_view.hpp
- include/mbgl/platform/default/settings_json.hpp
- include/mbgl/platform/default/thread_pool.hpp
+ # programs
+ src/mbgl/programs/attributes.hpp
+ src/mbgl/programs/circle_program.cpp
+ src/mbgl/programs/circle_program.hpp
+ src/mbgl/programs/collision_box_program.cpp
+ src/mbgl/programs/collision_box_program.hpp
+ src/mbgl/programs/debug_program.hpp
+ src/mbgl/programs/fill_program.cpp
+ src/mbgl/programs/fill_program.hpp
+ src/mbgl/programs/line_program.cpp
+ src/mbgl/programs/line_program.hpp
+ src/mbgl/programs/program.hpp
+ src/mbgl/programs/program_parameters.hpp
+ src/mbgl/programs/programs.hpp
+ src/mbgl/programs/raster_program.cpp
+ src/mbgl/programs/raster_program.hpp
+ src/mbgl/programs/symbol_program.cpp
+ src/mbgl/programs/symbol_program.hpp
+ src/mbgl/programs/uniforms.hpp
# renderer
src/mbgl/renderer/bucket.hpp
@@ -146,7 +153,6 @@ set(MBGL_CORE_FILES
src/mbgl/renderer/circle_bucket.hpp
src/mbgl/renderer/debug_bucket.cpp
src/mbgl/renderer/debug_bucket.hpp
- src/mbgl/renderer/element_group.hpp
src/mbgl/renderer/fill_bucket.cpp
src/mbgl/renderer/fill_bucket.hpp
src/mbgl/renderer/frame_history.cpp
@@ -173,45 +179,6 @@ set(MBGL_CORE_FILES
src/mbgl/renderer/symbol_bucket.cpp
src/mbgl/renderer/symbol_bucket.hpp
- # shader
- src/mbgl/shader/circle_shader.cpp
- src/mbgl/shader/circle_shader.hpp
- src/mbgl/shader/circle_vertex.cpp
- src/mbgl/shader/circle_vertex.hpp
- src/mbgl/shader/collision_box_shader.cpp
- src/mbgl/shader/collision_box_shader.hpp
- src/mbgl/shader/collision_box_vertex.cpp
- src/mbgl/shader/collision_box_vertex.hpp
- src/mbgl/shader/fill_outline_pattern_shader.cpp
- src/mbgl/shader/fill_outline_pattern_shader.hpp
- src/mbgl/shader/fill_outline_shader.cpp
- src/mbgl/shader/fill_outline_shader.hpp
- src/mbgl/shader/fill_pattern_shader.cpp
- src/mbgl/shader/fill_pattern_shader.hpp
- src/mbgl/shader/fill_shader.cpp
- src/mbgl/shader/fill_shader.hpp
- src/mbgl/shader/fill_vertex.cpp
- src/mbgl/shader/fill_vertex.hpp
- src/mbgl/shader/line_pattern_shader.cpp
- src/mbgl/shader/line_pattern_shader.hpp
- src/mbgl/shader/line_sdf_shader.cpp
- src/mbgl/shader/line_sdf_shader.hpp
- src/mbgl/shader/line_shader.cpp
- src/mbgl/shader/line_shader.hpp
- src/mbgl/shader/line_vertex.cpp
- src/mbgl/shader/line_vertex.hpp
- src/mbgl/shader/raster_shader.cpp
- src/mbgl/shader/raster_shader.hpp
- src/mbgl/shader/raster_vertex.cpp
- src/mbgl/shader/raster_vertex.hpp
- src/mbgl/shader/shaders.hpp
- src/mbgl/shader/symbol_icon_shader.cpp
- src/mbgl/shader/symbol_icon_shader.hpp
- src/mbgl/shader/symbol_sdf_shader.cpp
- src/mbgl/shader/symbol_sdf_shader.hpp
- src/mbgl/shader/symbol_vertex.cpp
- src/mbgl/shader/symbol_vertex.hpp
-
# sprite
include/mbgl/sprite/sprite_image.hpp
src/mbgl/sprite/sprite_atlas.cpp
@@ -248,10 +215,14 @@ set(MBGL_CORE_FILES
include/mbgl/style/types.hpp
src/mbgl/style/bucket_parameters.cpp
src/mbgl/style/bucket_parameters.hpp
- src/mbgl/style/calculation_parameters.hpp
src/mbgl/style/cascade_parameters.hpp
src/mbgl/style/class_dictionary.cpp
src/mbgl/style/class_dictionary.hpp
+ src/mbgl/style/cross_faded_property_evaluator.cpp
+ src/mbgl/style/cross_faded_property_evaluator.hpp
+ src/mbgl/style/function.cpp
+ src/mbgl/style/group_by_layout.cpp
+ src/mbgl/style/group_by_layout.hpp
src/mbgl/style/layer.cpp
src/mbgl/style/layer_impl.cpp
src/mbgl/style/layer_impl.hpp
@@ -261,7 +232,7 @@ set(MBGL_CORE_FILES
src/mbgl/style/paint_property.hpp
src/mbgl/style/parser.cpp
src/mbgl/style/parser.hpp
- src/mbgl/style/property_evaluator.cpp
+ src/mbgl/style/property_evaluation_parameters.hpp
src/mbgl/style/property_evaluator.hpp
src/mbgl/style/property_parsing.cpp
src/mbgl/style/property_parsing.hpp
@@ -291,11 +262,13 @@ set(MBGL_CORE_FILES
include/mbgl/style/conversion/property_value.hpp
include/mbgl/style/conversion/source.hpp
include/mbgl/style/conversion/tileset.hpp
+ src/mbgl/style/conversion/stringify.hpp
# style/layers
include/mbgl/style/layers/background_layer.hpp
include/mbgl/style/layers/circle_layer.hpp
include/mbgl/style/layers/custom_layer.hpp
+ include/mbgl/style/layers/fill_extrusion_layer.hpp
include/mbgl/style/layers/fill_layer.hpp
include/mbgl/style/layers/line_layer.hpp
include/mbgl/style/layers/raster_layer.hpp
@@ -313,6 +286,11 @@ set(MBGL_CORE_FILES
src/mbgl/style/layers/custom_layer.cpp
src/mbgl/style/layers/custom_layer_impl.cpp
src/mbgl/style/layers/custom_layer_impl.hpp
+ src/mbgl/style/layers/fill_extrusion_layer.cpp
+ src/mbgl/style/layers/fill_extrusion_layer_impl.cpp
+ src/mbgl/style/layers/fill_extrusion_layer_impl.hpp
+ src/mbgl/style/layers/fill_extrusion_layer_properties.cpp
+ src/mbgl/style/layers/fill_extrusion_layer_properties.hpp
src/mbgl/style/layers/fill_layer.cpp
src/mbgl/style/layers/fill_layer_impl.cpp
src/mbgl/style/layers/fill_layer_impl.hpp
@@ -349,6 +327,7 @@ set(MBGL_CORE_FILES
src/mbgl/style/sources/vector_source_impl.hpp
# text
+ src/mbgl/text/bidi.hpp
src/mbgl/text/check_max_angle.cpp
src/mbgl/text/check_max_angle.hpp
src/mbgl/text/collision_feature.cpp
@@ -406,8 +385,8 @@ set(MBGL_CORE_FILES
include/mbgl/util/compression.hpp
include/mbgl/util/constants.hpp
include/mbgl/util/convert.hpp
- include/mbgl/util/default_styles.hpp
include/mbgl/util/enum.hpp
+ include/mbgl/util/event.hpp
include/mbgl/util/exception.hpp
include/mbgl/util/feature.hpp
include/mbgl/util/font_stack.hpp
@@ -415,11 +394,14 @@ set(MBGL_CORE_FILES
include/mbgl/util/geojson.hpp
include/mbgl/util/geometry.hpp
include/mbgl/util/image.hpp
+ include/mbgl/util/logging.hpp
include/mbgl/util/noncopyable.hpp
include/mbgl/util/optional.hpp
+ include/mbgl/util/platform.hpp
include/mbgl/util/projection.hpp
include/mbgl/util/range.hpp
include/mbgl/util/run_loop.hpp
+ include/mbgl/util/size.hpp
include/mbgl/util/string.hpp
include/mbgl/util/tileset.hpp
include/mbgl/util/timer.hpp
@@ -438,9 +420,9 @@ set(MBGL_CORE_FILES
src/mbgl/util/compression.cpp
src/mbgl/util/constants.cpp
src/mbgl/util/convert.cpp
- src/mbgl/util/default_styles.cpp
src/mbgl/util/dtoa.cpp
src/mbgl/util/dtoa.hpp
+ src/mbgl/util/event.cpp
src/mbgl/util/exclusive.hpp
src/mbgl/util/font_stack.cpp
src/mbgl/util/geo.cpp
@@ -451,11 +433,16 @@ set(MBGL_CORE_FILES
src/mbgl/util/http_header.hpp
src/mbgl/util/http_timeout.cpp
src/mbgl/util/http_timeout.hpp
+ src/mbgl/util/i18n.cpp
+ src/mbgl/util/i18n.hpp
+ src/mbgl/util/ignore.hpp
+ src/mbgl/util/indexed_tuple.hpp
src/mbgl/util/interpolate.hpp
src/mbgl/util/intersection_tests.cpp
src/mbgl/util/intersection_tests.hpp
src/mbgl/util/io.cpp
src/mbgl/util/io.hpp
+ src/mbgl/util/logging.cpp
src/mbgl/util/mapbox.cpp
src/mbgl/util/mapbox.hpp
src/mbgl/util/mat2.cpp
@@ -464,7 +451,6 @@ set(MBGL_CORE_FILES
src/mbgl/util/mat3.hpp
src/mbgl/util/mat4.cpp
src/mbgl/util/mat4.hpp
- src/mbgl/util/math.cpp
src/mbgl/util/math.hpp
src/mbgl/util/offscreen_texture.cpp
src/mbgl/util/offscreen_texture.hpp
diff --git a/cmake/core.cmake b/cmake/core.cmake
index bc5e7eb718..8d8a942d9f 100644
--- a/cmake/core.cmake
+++ b/cmake/core.cmake
@@ -45,6 +45,7 @@ target_add_mason_package(mbgl-core PRIVATE supercluster)
target_add_mason_package(mbgl-core PRIVATE kdbush)
target_add_mason_package(mbgl-core PRIVATE earcut)
target_add_mason_package(mbgl-core PRIVATE protozero)
+target_add_mason_package(mbgl-core PRIVATE polylabel)
mbgl_platform_core()
diff --git a/cmake/glfw.cmake b/cmake/glfw.cmake
index 56a1335e08..d63bdbc1cf 100644
--- a/cmake/glfw.cmake
+++ b/cmake/glfw.cmake
@@ -1,12 +1,14 @@
add_executable(mbgl-glfw
- bin/glfw.cpp
+ platform/glfw/main.cpp
)
target_sources(mbgl-glfw
- PRIVATE include/mbgl/platform/default/glfw_view.hpp
- PRIVATE platform/default/glfw_view.cpp
- PRIVATE include/mbgl/platform/default/settings_json.hpp
- PRIVATE platform/default/settings_json.cpp
+ PRIVATE platform/glfw/glfw_view.hpp
+ PRIVATE platform/glfw/glfw_view.cpp
+ PRIVATE platform/glfw/settings_json.hpp
+ PRIVATE platform/glfw/settings_json.cpp
+ PRIVATE platform/default/mbgl/util/default_styles.hpp
+ PRIVATE platform/default/mbgl/util/default_styles.cpp
)
target_compile_options(mbgl-glfw
@@ -16,6 +18,7 @@ target_compile_options(mbgl-glfw
target_include_directories(mbgl-glfw
PRIVATE include
PRIVATE src # TODO: eliminate
+ PRIVATE platform/default
)
target_link_libraries(mbgl-glfw
diff --git a/cmake/loop-darwin.cmake b/cmake/loop-darwin.cmake
index 16bc62537c..7884c80a69 100644
--- a/cmake/loop-darwin.cmake
+++ b/cmake/loop-darwin.cmake
@@ -4,6 +4,8 @@ add_library(mbgl-loop STATIC
platform/darwin/src/timer.cpp
)
+set_xcode_property(mbgl-loop GCC_SYMBOLS_PRIVATE_EXTERN YES)
+
target_compile_options(mbgl-loop
PRIVATE -fPIC
PRIVATE -fvisibility-inlines-hidden
diff --git a/cmake/mbgl.cmake b/cmake/mbgl.cmake
index f20f49004c..b2b959e6c1 100644
--- a/cmake/mbgl.cmake
+++ b/cmake/mbgl.cmake
@@ -35,6 +35,11 @@ function(create_source_groups target)
endforeach()
endfunction()
+# This little macro lets you set any XCode specific property
+macro(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
+ set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
+endmacro (set_xcode_property)
+
function(_write_xcconfig_var target var)
get_property(result TARGET ${target} PROPERTY INTERFACE_${var} SET)
if (result)
diff --git a/cmake/node.cmake b/cmake/node.cmake
index 8dd95a9419..ea28e86106 100644
--- a/cmake/node.cmake
+++ b/cmake/node.cmake
@@ -3,8 +3,8 @@ add_nodejs_module(mbgl-node
)
target_sources(mbgl-node
- PRIVATE platform/node/src/node_log.hpp
- PRIVATE platform/node/src/node_log.cpp
+ PRIVATE platform/node/src/node_logging.hpp
+ PRIVATE platform/node/src/node_logging.cpp
PRIVATE platform/node/src/node_map.hpp
PRIVATE platform/node/src/node_map.cpp
PRIVATE platform/node/src/node_request.hpp
@@ -29,6 +29,7 @@ target_compile_options(mbgl-node
target_include_directories(mbgl-node
PRIVATE src # TODO: eliminate
+ PRIVATE platform/default
)
target_link_libraries(mbgl-node
diff --git a/cmake/offline.cmake b/cmake/offline.cmake
index 1dc67f7887..23824e6bdf 100644
--- a/cmake/offline.cmake
+++ b/cmake/offline.cmake
@@ -2,6 +2,11 @@ add_executable(mbgl-offline
bin/offline.cpp
)
+target_sources(mbgl-offline
+ PRIVATE platform/default/mbgl/util/default_styles.hpp
+ PRIVATE platform/default/mbgl/util/default_styles.cpp
+)
+
target_compile_options(mbgl-offline
PRIVATE -fvisibility-inlines-hidden
)
@@ -9,6 +14,7 @@ target_compile_options(mbgl-offline
target_include_directories(mbgl-offline
PRIVATE include
PRIVATE src # TODO: eliminate
+ PRIVATE platform/default
)
target_link_libraries(mbgl-offline
diff --git a/cmake/render.cmake b/cmake/render.cmake
index f1b09b3c47..395a106642 100644
--- a/cmake/render.cmake
+++ b/cmake/render.cmake
@@ -9,6 +9,7 @@ target_compile_options(mbgl-render
target_include_directories(mbgl-render
PRIVATE include
PRIVATE src # TODO: eliminate
+ PRIVATE platform/default
)
target_link_libraries(mbgl-render
diff --git a/cmake/shaders.cmake b/cmake/shaders.cmake
index bebf476bbf..fc6575537a 100644
--- a/cmake/shaders.cmake
+++ b/cmake/shaders.cmake
@@ -1,17 +1,19 @@
function(add_shader VAR name)
set(shader_build_cmd ${NodeJS_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/build-shaders.js)
- set(shader_file_prefix ${CMAKE_SOURCE_DIR}/node_modules/mapbox-gl-shaders/src)
+ set(shader_file_prefix ${CMAKE_SOURCE_DIR}/mapbox-gl-js/shaders)
set(shader_source_prefix ${MBGL_GENERATED}/include/mbgl/shader)
add_custom_command(
- OUTPUT ${shader_source_prefix}/${name}.vertex.hpp ${shader_source_prefix}/${name}.fragment.hpp
- COMMAND ${shader_build_cmd} ${shader_file_prefix}/${name}.vertex.glsl ${shader_source_prefix}/${name}.vertex.hpp
- COMMAND ${shader_build_cmd} ${shader_file_prefix}/${name}.fragment.glsl ${shader_source_prefix}/${name}.fragment.hpp
+ OUTPUT ${shader_source_prefix}/${name}.hpp
+ COMMAND ${shader_build_cmd} ${name} ${shader_file_prefix} ${shader_source_prefix}
+ DEPENDS ${CMAKE_SOURCE_DIR}/scripts/build-shaders.js
DEPENDS ${shader_file_prefix}/${name}.vertex.glsl
DEPENDS ${shader_file_prefix}/${name}.fragment.glsl
+ DEPENDS ${shader_file_prefix}/_prelude.vertex.glsl
+ DEPENDS ${shader_file_prefix}/_prelude.fragment.glsl
VERBATIM
)
- set(${VAR} ${${VAR}} ${shader_source_prefix}/${name}.vertex.hpp ${shader_source_prefix}/${name}.fragment.hpp PARENT_SCOPE)
+ set(${VAR} ${${VAR}} ${shader_source_prefix}/${name}.hpp PARENT_SCOPE)
endfunction()
add_shader(MBGL_SHADER_FILES circle)
diff --git a/cmake/test-files.cmake b/cmake/test-files.cmake
index 598e018224..32ee236994 100644
--- a/cmake/test-files.cmake
+++ b/cmake/test-files.cmake
@@ -23,6 +23,7 @@ set(MBGL_TEST_FILES
test/geometry/binpack.test.cpp
# gl
+ test/gl/bucket.test.cpp
test/gl/object.test.cpp
# include/mbgl
@@ -71,11 +72,14 @@ set(MBGL_TEST_FILES
test/storage/resource.test.cpp
# style/conversion
+ test/style/conversion/function.test.cpp
test/style/conversion/geojson_options.test.cpp
+ test/style/conversion/stringify.test.cpp
# style
test/style/filter.test.cpp
test/style/functions.test.cpp
+ test/style/group_by_layout.test.cpp
test/style/source.test.cpp
test/style/style.test.cpp
test/style/style_layer.test.cpp
@@ -87,6 +91,7 @@ set(MBGL_TEST_FILES
test/text/quads.test.cpp
# tile
+ test/tile/geojson_tile.test.cpp
test/tile/geometry_tile_data.test.cpp
test/tile/raster_tile.test.cpp
test/tile/tile_coordinate.test.cpp
@@ -111,5 +116,6 @@ set(MBGL_TEST_FILES
test/util/tile_cover.test.cpp
test/util/timer.test.cpp
test/util/token.test.cpp
+ test/util/url.test.cpp
test/util/work_queue.test.cpp
)
diff --git a/cmake/test.cmake b/cmake/test.cmake
index c4d9dd9fad..fc7a22874c 100644
--- a/cmake/test.cmake
+++ b/cmake/test.cmake
@@ -14,14 +14,9 @@ target_include_directories(mbgl-test
PRIVATE test/include
PRIVATE test/src
PRIVATE platform/default
+ PRIVATE ${MBGL_GENERATED}/include
)
-if(DEFINED ENV{CI})
- target_compile_definitions(mbgl-test
- PRIVATE -DCI_BUILD=1
- )
-endif()
-
target_link_libraries(mbgl-test
PRIVATE mbgl-core
)
diff --git a/include/mbgl/gl/implementation.hpp b/include/mbgl/gl/implementation.hpp
deleted file mode 100644
index a0101085fa..0000000000
--- a/include/mbgl/gl/implementation.hpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-#if defined(__QT__)
- #define MBGL_USE_QT 1
-#elif defined(__APPLE__)
- #include <TargetConditionals.h>
- #if TARGET_OS_IOS
- #define MBGL_USE_EAGL 1
- #else
- #define MBGL_USE_CGL 1
- #endif
-#elif defined(__OSMESA__)
- #define MBGL_USE_OSMESA 1
-#else
- #define MBGL_USE_GLX 1
-#endif
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp
index 092cfbe291..c80420371d 100644
--- a/include/mbgl/map/map.hpp
+++ b/include/mbgl/map/map.hpp
@@ -6,6 +6,7 @@
#include <mbgl/util/geo.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/size.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/style/transition_options.hpp>
@@ -33,7 +34,7 @@ class Layer;
class Map : private util::noncopyable {
public:
explicit Map(Backend&,
- std::array<uint16_t, 2> size,
+ Size size,
float pixelRatio,
FileSource&,
Scheduler&,
@@ -136,9 +137,8 @@ public:
ViewportMode getViewportMode() const;
// Size
- void setSize(const std::array<uint16_t, 2>&);
- uint16_t getWidth() const;
- uint16_t getHeight() const;
+ void setSize(Size);
+ Size getSize() const;
// Projection
double getMetersPerPixelAtLatitude(double lat, double zoom) const;
diff --git a/include/mbgl/math/log2.hpp b/include/mbgl/math/log2.hpp
new file mode 100644
index 0000000000..8a3bc7f1c0
--- /dev/null
+++ b/include/mbgl/math/log2.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <cmath>
+#include <cstdint>
+#include <type_traits>
+
+namespace mbgl {
+namespace util {
+
+// Computes the log2(x) rounded up to the next integer.
+// (== number of bits required to store x)
+uint32_t ceil_log2(uint64_t x);
+
+template <typename T>
+typename std::enable_if_t<std::is_floating_point<T>::value, T> log2(T x)
+{
+// log2() is producing wrong results on ARMv5 binaries
+// running on ARMv7+ CPUs.
+#if defined(__ANDROID__)
+ return std::log(x) / M_LN2;
+#else
+ return std::log2(x);
+#endif
+}
+
+} // namespace util
+} // namespace mbgl
diff --git a/include/mbgl/mbgl.hpp b/include/mbgl/mbgl.hpp
deleted file mode 100644
index 5cfc9cb45f..0000000000
--- a/include/mbgl/mbgl.hpp
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-#include "map/map.hpp"
-#include "map/view.hpp"
diff --git a/include/mbgl/platform/default/headless_display.hpp b/include/mbgl/platform/default/headless_display.hpp
deleted file mode 100644
index f43e61340f..0000000000
--- a/include/mbgl/platform/default/headless_display.hpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/implementation.hpp>
-
-#if MBGL_USE_CGL
-#include <OpenGL/OpenGL.h>
-#elif MBGL_USE_GLX
-typedef struct _XDisplay Display;
-typedef struct __GLXFBConfigRec* GLXFBConfig;
-#endif
-
-namespace mbgl {
-
-class HeadlessDisplay {
-public:
- HeadlessDisplay();
- ~HeadlessDisplay();
-
-#if MBGL_USE_CGL
- CGLPixelFormatObj pixelFormat = nullptr;
-#endif
-
-#if MBGL_USE_GLX
- Display *xDisplay = nullptr;
- GLXFBConfig *fbConfigs = nullptr;
-#endif
-};
-
-} // namespace mbgl
diff --git a/include/mbgl/sprite/sprite_image.hpp b/include/mbgl/sprite/sprite_image.hpp
index 7900b90b66..05d9871bf9 100644
--- a/include/mbgl/sprite/sprite_image.hpp
+++ b/include/mbgl/sprite/sprite_image.hpp
@@ -22,8 +22,8 @@ public:
// Whether this image should be interpreted as a signed distance field icon.
const bool sdf;
- float getWidth() const { return image.width / pixelRatio; }
- float getHeight() const { return image.height / pixelRatio; }
+ float getWidth() const { return image.size.width / pixelRatio; }
+ float getHeight() const { return image.size.height / pixelRatio; }
};
} // namespace mbgl
diff --git a/include/mbgl/style/conversion/function.hpp b/include/mbgl/style/conversion/function.hpp
index f14b5089be..6a0b67618f 100644
--- a/include/mbgl/style/conversion/function.hpp
+++ b/include/mbgl/style/conversion/function.hpp
@@ -25,6 +25,10 @@ struct Converter<Function<T>> {
return Error { "function stops must be an array" };
}
+ if (arrayLength(*stopsValue) == 0) {
+ return Error { "function must have at least one stop" };
+ }
+
std::vector<std::pair<float, T>> stops;
for (std::size_t i = 0; i < arrayLength(*stopsValue); ++i) {
const auto& stopValue = arrayMember(*stopsValue, i);
diff --git a/include/mbgl/style/conversion/make_property_setters.hpp b/include/mbgl/style/conversion/make_property_setters.hpp
index a3ba5e5d5a..e30359937e 100644
--- a/include/mbgl/style/conversion/make_property_setters.hpp
+++ b/include/mbgl/style/conversion/make_property_setters.hpp
@@ -8,6 +8,7 @@
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
#include <mbgl/style/layers/raster_layer.hpp>
#include <mbgl/style/layers/background_layer.hpp>
@@ -67,6 +68,7 @@ auto makeLayoutPropertySetters() {
+
return result;
}
@@ -115,6 +117,17 @@ auto makePaintPropertySetters() {
result["circle-translate"] = makePropertySetter<V>(&CircleLayer::setCircleTranslate);
result["circle-translate-anchor"] = makePropertySetter<V>(&CircleLayer::setCircleTranslateAnchor);
result["circle-pitch-scale"] = makePropertySetter<V>(&CircleLayer::setCirclePitchScale);
+ result["circle-stroke-width"] = makePropertySetter<V>(&CircleLayer::setCircleStrokeWidth);
+ result["circle-stroke-color"] = makePropertySetter<V>(&CircleLayer::setCircleStrokeColor);
+ result["circle-stroke-opacity"] = makePropertySetter<V>(&CircleLayer::setCircleStrokeOpacity);
+
+ result["fill-extrusion-opacity"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionOpacity);
+ result["fill-extrusion-color"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionColor);
+ result["fill-extrusion-translate"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionTranslate);
+ result["fill-extrusion-translate-anchor"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionTranslateAnchor);
+ result["fill-extrusion-pattern"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionPattern);
+ result["fill-extrusion-height"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionHeight);
+ result["fill-extrusion-base"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionBase);
result["raster-opacity"] = makePropertySetter<V>(&RasterLayer::setRasterOpacity);
result["raster-hue-rotate"] = makePropertySetter<V>(&RasterLayer::setRasterHueRotate);
diff --git a/include/mbgl/style/conversion/make_property_setters.hpp.ejs b/include/mbgl/style/conversion/make_property_setters.hpp.ejs
index 54e3958180..ed8f6e891c 100644
--- a/include/mbgl/style/conversion/make_property_setters.hpp.ejs
+++ b/include/mbgl/style/conversion/make_property_setters.hpp.ejs
@@ -5,7 +5,7 @@
#include <mbgl/style/conversion/property_setter.hpp>
<% for (const layer of locals.layers) { -%>
-#include <mbgl/style/layers/<%- layer.type %>_layer.hpp>
+#include <mbgl/style/layers/<%- layer.type.replace('-', '_') %>_layer.hpp>
<% } -%>
#include <unordered_map>
diff --git a/include/mbgl/style/filter_evaluator.hpp b/include/mbgl/style/filter_evaluator.hpp
index cf9877da26..659f554bba 100644
--- a/include/mbgl/style/filter_evaluator.hpp
+++ b/include/mbgl/style/filter_evaluator.hpp
@@ -173,8 +173,8 @@ private:
return false;
}
- bool operator()(const std::unordered_map<std::string, Value>&,
- const std::unordered_map<std::string, Value>&) const {
+ bool operator()(const PropertyMap&,
+ const PropertyMap&) const {
// Should be unreachable; nested values are not currently allowed by the style specification.
assert(false);
return false;
diff --git a/include/mbgl/style/function.hpp b/include/mbgl/style/function.hpp
index 97e880b280..b023229e4f 100644
--- a/include/mbgl/style/function.hpp
+++ b/include/mbgl/style/function.hpp
@@ -1,7 +1,8 @@
#pragma once
-#include <vector>
+#include <cassert>
#include <utility>
+#include <vector>
namespace mbgl {
namespace style {
@@ -12,28 +13,28 @@ public:
using Stop = std::pair<float, T>;
using Stops = std::vector<Stop>;
- explicit Function(Stops stops_, float base_)
- : base(base_), stops(std::move(stops_)) {}
+ Function(Stops stops_, float base_)
+ : base(base_), stops(std::move(stops_)) {
+ assert(stops.size() > 0);
+ }
float getBase() const { return base; }
const std::vector<std::pair<float, T>>& getStops() const { return stops; }
+ T evaluate(float z) const;
+
+ friend bool operator==(const Function& lhs, const Function& rhs) {
+ return lhs.base == rhs.base && lhs.stops == rhs.stops;
+ }
+
+ friend bool operator!=(const Function& lhs, const Function& rhs) {
+ return !(lhs == rhs);
+ }
+
private:
float base = 1;
std::vector<std::pair<float, T>> stops;
-
- template <class S> friend bool operator==(const Function<S>&, const Function<S>&);
};
-template <class T>
-bool operator==(const Function<T>& lhs, const Function<T>& rhs) {
- return lhs.base == rhs.base && lhs.stops == rhs.stops;
-}
-
-template <class T>
-bool operator!=(const Function<T>& lhs, const Function<T>& rhs) {
- return !(lhs == rhs);
-}
-
} // namespace style
} // namespace mbgl
diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp
index 925629a349..5936422c74 100644
--- a/include/mbgl/style/layer.hpp
+++ b/include/mbgl/style/layer.hpp
@@ -15,6 +15,7 @@ class SymbolLayer;
class RasterLayer;
class BackgroundLayer;
class CustomLayer;
+class FillExtrusionLayer;
/**
* The runtime representation of a [layer](https://www.mapbox.com/mapbox-gl-style-spec/#layers) from the Mapbox Style
@@ -42,6 +43,7 @@ protected:
Raster,
Background,
Custom,
+ FillExtrusion,
};
class Impl;
@@ -95,6 +97,8 @@ public:
return visitor(*as<BackgroundLayer>());
case Type::Custom:
return visitor(*as<CustomLayer>());
+ case Type::FillExtrusion:
+ return visitor(*as<FillExtrusionLayer>());
}
}
@@ -112,6 +116,8 @@ public:
// Private implementation
const std::unique_ptr<Impl> baseImpl;
+
+ friend std::string layoutKey(const Layer&);
};
} // namespace style
diff --git a/include/mbgl/style/layers/circle_layer.hpp b/include/mbgl/style/layers/circle_layer.hpp
index 587f0023e3..5562126c2f 100644
--- a/include/mbgl/style/layers/circle_layer.hpp
+++ b/include/mbgl/style/layers/circle_layer.hpp
@@ -54,6 +54,18 @@ public:
PropertyValue<CirclePitchScaleType> getCirclePitchScale(const optional<std::string>& klass = {}) const;
void setCirclePitchScale(PropertyValue<CirclePitchScaleType>, const optional<std::string>& klass = {});
+ static PropertyValue<float> getDefaultCircleStrokeWidth();
+ PropertyValue<float> getCircleStrokeWidth(const optional<std::string>& klass = {}) const;
+ void setCircleStrokeWidth(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ static PropertyValue<Color> getDefaultCircleStrokeColor();
+ PropertyValue<Color> getCircleStrokeColor(const optional<std::string>& klass = {}) const;
+ void setCircleStrokeColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+
+ static PropertyValue<float> getDefaultCircleStrokeOpacity();
+ PropertyValue<float> getCircleStrokeOpacity(const optional<std::string>& klass = {}) const;
+ void setCircleStrokeOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+
// Private implementation
class Impl;
diff --git a/include/mbgl/style/layers/custom_layer.hpp b/include/mbgl/style/layers/custom_layer.hpp
index 1b62f82a25..6bde087820 100644
--- a/include/mbgl/style/layers/custom_layer.hpp
+++ b/include/mbgl/style/layers/custom_layer.hpp
@@ -25,7 +25,7 @@ struct CustomLayerRenderParameters {
double zoom;
double bearing;
double pitch;
- double altitude;
+ double fieldOfView;
};
/**
diff --git a/include/mbgl/style/layers/fill_extrusion_layer.hpp b/include/mbgl/style/layers/fill_extrusion_layer.hpp
new file mode 100644
index 0000000000..08728af309
--- /dev/null
+++ b/include/mbgl/style/layers/fill_extrusion_layer.hpp
@@ -0,0 +1,72 @@
+// This file is generated. Do not edit.
+
+#pragma once
+
+#include <mbgl/style/layer.hpp>
+#include <mbgl/style/filter.hpp>
+#include <mbgl/style/property_value.hpp>
+
+#include <mbgl/util/color.hpp>
+
+namespace mbgl {
+namespace style {
+
+class FillExtrusionLayer : public Layer {
+public:
+ FillExtrusionLayer(const std::string& layerID, const std::string& sourceID);
+ ~FillExtrusionLayer() final;
+
+ // Source
+ const std::string& getSourceID() const;
+ const std::string& getSourceLayer() const;
+ void setSourceLayer(const std::string& sourceLayer);
+
+ void setFilter(const Filter&);
+ const Filter& getFilter() const;
+
+ // Paint properties
+
+ static PropertyValue<float> getDefaultFillExtrusionOpacity();
+ PropertyValue<float> getFillExtrusionOpacity(const optional<std::string>& klass = {}) const;
+ void setFillExtrusionOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ static PropertyValue<Color> getDefaultFillExtrusionColor();
+ PropertyValue<Color> getFillExtrusionColor(const optional<std::string>& klass = {}) const;
+ void setFillExtrusionColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+
+ static PropertyValue<std::array<float, 2>> getDefaultFillExtrusionTranslate();
+ PropertyValue<std::array<float, 2>> getFillExtrusionTranslate(const optional<std::string>& klass = {}) const;
+ void setFillExtrusionTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {});
+
+ static PropertyValue<TranslateAnchorType> getDefaultFillExtrusionTranslateAnchor();
+ PropertyValue<TranslateAnchorType> getFillExtrusionTranslateAnchor(const optional<std::string>& klass = {}) const;
+ void setFillExtrusionTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {});
+
+ static PropertyValue<std::string> getDefaultFillExtrusionPattern();
+ PropertyValue<std::string> getFillExtrusionPattern(const optional<std::string>& klass = {}) const;
+ void setFillExtrusionPattern(PropertyValue<std::string>, const optional<std::string>& klass = {});
+
+ static PropertyValue<float> getDefaultFillExtrusionHeight();
+ PropertyValue<float> getFillExtrusionHeight(const optional<std::string>& klass = {}) const;
+ void setFillExtrusionHeight(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ static PropertyValue<float> getDefaultFillExtrusionBase();
+ PropertyValue<float> getFillExtrusionBase(const optional<std::string>& klass = {}) const;
+ void setFillExtrusionBase(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ // Private implementation
+
+ class Impl;
+ Impl* const impl;
+
+ FillExtrusionLayer(const Impl&);
+ FillExtrusionLayer(const FillExtrusionLayer&) = delete;
+};
+
+template <>
+inline bool Layer::is<FillExtrusionLayer>() const {
+ return type == Type::FillExtrusion;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/property_value.hpp b/include/mbgl/style/property_value.hpp
index d7e160fdca..83c4b4cf1b 100644
--- a/include/mbgl/style/property_value.hpp
+++ b/include/mbgl/style/property_value.hpp
@@ -17,7 +17,13 @@ private:
using Value = variant<Undefined, T, Function<T>>;
Value value;
- template <class S> friend bool operator==(const PropertyValue<S>&, const PropertyValue<S>&);
+ friend bool operator==(const PropertyValue& lhs, const PropertyValue& rhs) {
+ return lhs.value == rhs.value;
+ }
+
+ friend bool operator!=(const PropertyValue& lhs, const PropertyValue& rhs) {
+ return !(lhs == rhs);
+ }
public:
PropertyValue() : value() {}
@@ -33,21 +39,11 @@ public:
explicit operator bool() const { return !isUndefined(); };
- template <typename Visitor>
- static auto visit(const PropertyValue<T>& value, Visitor&& visitor) {
- return Value::visit(value.value, visitor);
+ template <typename Evaluator>
+ auto evaluate(const Evaluator& evaluator) const {
+ return Value::visit(value, evaluator);
}
};
-template <class T>
-bool operator==(const PropertyValue<T>& lhs, const PropertyValue<T>& rhs) {
- return lhs.value == rhs.value;
-}
-
-template <class T>
-bool operator!=(const PropertyValue<T>& lhs, const PropertyValue<T>& rhs) {
- return !(lhs == rhs);
-}
-
} // namespace style
} // namespace mbgl
diff --git a/include/mbgl/style/transition_options.hpp b/include/mbgl/style/transition_options.hpp
index d7a6633f0c..e2a156e665 100644
--- a/include/mbgl/style/transition_options.hpp
+++ b/include/mbgl/style/transition_options.hpp
@@ -6,9 +6,21 @@
namespace mbgl {
namespace style {
-struct TransitionOptions {
+class TransitionOptions {
+public:
optional<Duration> duration = {};
optional<Duration> delay = {};
+
+ TransitionOptions reverseMerge(const TransitionOptions& defaults) const {
+ return {
+ duration ? duration : defaults.duration,
+ delay ? delay : defaults.delay
+ };
+ }
+
+ explicit operator bool() const {
+ return duration || delay;
+ }
};
} // namespace style
diff --git a/include/mbgl/util/color.hpp b/include/mbgl/util/color.hpp
index 4be380fde3..300d7fae82 100644
--- a/include/mbgl/util/color.hpp
+++ b/include/mbgl/util/color.hpp
@@ -2,6 +2,7 @@
#include <mbgl/util/optional.hpp>
+#include <cassert>
#include <string>
namespace mbgl {
@@ -9,26 +10,46 @@ namespace mbgl {
// Stores a premultiplied color, with all four channels ranging from 0..1
class Color {
public:
+ Color() = default;
+ Color(float r_, float g_, float b_, float a_)
+ : r(r_), g(g_), b(b_), a(a_) {
+ assert(r_ >= 0.0f);
+ assert(r_ <= 1.0f);
+ assert(g_ >= 0.0f);
+ assert(g_ <= 1.0f);
+ assert(b_ >= 0.0f);
+ assert(b_ <= 1.0f);
+ assert(a_ >= 0.0f);
+ assert(a_ <= 1.0f);
+ }
+
float r = 0.0f;
float g = 0.0f;
float b = 0.0f;
float a = 0.0f;
- static constexpr Color black() { return { 0.0f, 0.0f, 0.0f, 1.0f }; };
- static constexpr Color white() { return { 1.0f, 1.0f, 1.0f, 1.0f }; };
+ static Color black() { return { 0.0f, 0.0f, 0.0f, 1.0f }; };
+ static Color white() { return { 1.0f, 1.0f, 1.0f, 1.0f }; };
+
+ static Color red() { return { 1.0f, 0.0f, 0.0f, 1.0f }; };
+ static Color green() { return { 0.0f, 1.0f, 0.0f, 1.0f }; };
+ static Color blue() { return { 0.0f, 0.0f, 1.0f, 1.0f }; };
static optional<Color> parse(const std::string&);
+ std::string stringify() const;
};
-constexpr bool operator==(const Color& colorA, const Color& colorB) {
+inline bool operator==(const Color& colorA, const Color& colorB) {
return colorA.r == colorB.r && colorA.g == colorB.g && colorA.b == colorB.b && colorA.a == colorB.a;
}
-constexpr bool operator!=(const Color& colorA, const Color& colorB) {
+inline bool operator!=(const Color& colorA, const Color& colorB) {
return !(colorA == colorB);
}
-constexpr Color operator*(const Color& color, float alpha) {
+inline Color operator*(const Color& color, float alpha) {
+ assert(alpha >= 0.0f);
+ assert(alpha <= 1.0f);
return {
color.r * alpha,
color.g * alpha,
diff --git a/include/mbgl/util/constants.hpp b/include/mbgl/util/constants.hpp
index e6e9f6e67d..85e19c2ff0 100644
--- a/include/mbgl/util/constants.hpp
+++ b/include/mbgl/util/constants.hpp
@@ -35,6 +35,8 @@ constexpr double DEGREES_MAX = 360;
constexpr double PITCH_MAX = M_PI / 3;
constexpr double MIN_ZOOM = 0.0;
constexpr double MAX_ZOOM = 25.5;
+constexpr float MIN_ZOOM_F = MIN_ZOOM;
+constexpr float MAX_ZOOM_F = MAX_ZOOM;
constexpr uint64_t DEFAULT_MAX_CACHE_SIZE = 50 * 1024 * 1024;
diff --git a/include/mbgl/platform/event.hpp b/include/mbgl/util/event.hpp
index 7ad3d914e8..7ad3d914e8 100644
--- a/include/mbgl/platform/event.hpp
+++ b/include/mbgl/util/event.hpp
diff --git a/include/mbgl/util/exception.hpp b/include/mbgl/util/exception.hpp
index 7c331636d4..46de8528c7 100644
--- a/include/mbgl/util/exception.hpp
+++ b/include/mbgl/util/exception.hpp
@@ -20,10 +20,5 @@ struct MisuseException : Exception {
MisuseException(const std::string &msg) : Exception(msg) {}
};
-struct ShaderException : Exception {
- ShaderException(const char *msg) : Exception(msg) {}
- ShaderException(const std::string &msg) : Exception(msg) {}
-};
-
} // namespace util
} // namespace mbgl
diff --git a/include/mbgl/util/image.hpp b/include/mbgl/util/image.hpp
index 795d1f9d1a..1d84d4824a 100644
--- a/include/mbgl/util/image.hpp
+++ b/include/mbgl/util/image.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/size.hpp>
#include <string>
#include <memory>
@@ -8,9 +9,10 @@
namespace mbgl {
-enum ImageAlphaMode {
+enum class ImageAlphaMode {
Unassociated,
- Premultiplied
+ Premultiplied,
+ Exclusive, // Alpha-channel only
};
template <ImageAlphaMode Mode>
@@ -18,44 +20,45 @@ class Image : private util::noncopyable {
public:
Image() = default;
- Image(uint16_t w, uint16_t h)
- : width(w),
- height(h),
- data(std::make_unique<uint8_t[]>(size())) {}
+ Image(Size size_)
+ : size(std::move(size_)),
+ data(std::make_unique<uint8_t[]>(bytes())) {}
- Image(uint16_t w, uint16_t h, std::unique_ptr<uint8_t[]> data_)
- : width(w),
- height(h),
+ Image(Size size_, std::unique_ptr<uint8_t[]> data_)
+ : size(std::move(size_)),
data(std::move(data_)) {}
Image(Image&& o)
- : width(o.width),
- height(o.height),
+ : size(o.size),
data(std::move(o.data)) {}
Image& operator=(Image&& o) {
- width = o.width;
- height = o.height;
+ size = o.size;
data = std::move(o.data);
return *this;
}
bool operator==(const Image& rhs) const {
- return width == rhs.width && height == rhs.height &&
- std::equal(data.get(), data.get() + size(), rhs.data.get(),
- rhs.data.get() + rhs.size());
+ return size == rhs.size &&
+ std::equal(data.get(), data.get() + bytes(), rhs.data.get(),
+ rhs.data.get() + rhs.bytes());
}
- size_t stride() const { return static_cast<size_t>(width) * 4; }
- size_t size() const { return static_cast<size_t>(width) * height * 4; }
+ bool valid() const {
+ return size && data.get() != nullptr;
+ }
+
+ size_t stride() const { return channels * size.width; }
+ size_t bytes() const { return stride() * size.height; }
- uint16_t width = 0;
- uint16_t height = 0;
+ Size size;
+ static constexpr size_t channels = Mode == ImageAlphaMode::Exclusive ? 1 : 4;
std::unique_ptr<uint8_t[]> data;
};
using UnassociatedImage = Image<ImageAlphaMode::Unassociated>;
using PremultipliedImage = Image<ImageAlphaMode::Premultiplied>;
+using AlphaImage = Image<ImageAlphaMode::Exclusive>;
// TODO: don't use std::string for binary data.
PremultipliedImage decodeImage(const std::string&);
diff --git a/include/mbgl/platform/log.hpp b/include/mbgl/util/logging.hpp
index d5bb1c2fcc..d072673e76 100644
--- a/include/mbgl/platform/log.hpp
+++ b/include/mbgl/util/logging.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <mbgl/platform/event.hpp>
+#include <mbgl/util/event.hpp>
#include <mbgl/util/noncopyable.hpp>
diff --git a/include/mbgl/platform/platform.hpp b/include/mbgl/util/platform.hpp
index cc8327c470..cc8327c470 100644
--- a/include/mbgl/platform/platform.hpp
+++ b/include/mbgl/util/platform.hpp
diff --git a/include/mbgl/util/range.hpp b/include/mbgl/util/range.hpp
index 8da2dd45bb..f7fa92eb8b 100644
--- a/include/mbgl/util/range.hpp
+++ b/include/mbgl/util/range.hpp
@@ -5,7 +5,7 @@ namespace mbgl {
template <class T>
class Range {
public:
- Range(const T& min_, const T& max_)
+ constexpr Range(const T& min_, const T& max_)
: min(min_), max(max_) {}
T min;
diff --git a/include/mbgl/util/size.hpp b/include/mbgl/util/size.hpp
new file mode 100644
index 0000000000..1af85bcff5
--- /dev/null
+++ b/include/mbgl/util/size.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <cstdint>
+#include <array>
+
+namespace mbgl {
+
+class Size {
+public:
+ constexpr Size() : width(0), height(0) {
+ }
+
+ constexpr Size(const uint32_t width_, const uint32_t height_) : width(width_), height(height_) {
+ }
+
+ constexpr explicit operator bool() const {
+ return width > 0 && height > 0;
+ }
+
+ uint32_t width;
+ uint32_t height;
+};
+
+constexpr inline bool operator==(const Size& a, const Size& b) {
+ return a.width == b.width && a.height == b.height;
+}
+
+constexpr inline bool operator!=(const Size& a, const Size& b) {
+ return !(a == b);
+}
+
+} // namespace mbgl
diff --git a/mapbox-gl-js b/mapbox-gl-js
new file mode 160000
+Subproject 878008895104b67861ce73f65809f7f6f0ed726
diff --git a/package.json b/package.json
index 7abe377a47..5a9e159cc5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
- "name": "mapbox-gl-native",
- "version": "3.3.3",
+ "name": "@mapbox/mapbox-gl-native",
+ "version": "3.4.4",
"description": "Renders map tiles with Mapbox GL",
"keywords": [
"mapbox",
@@ -13,7 +13,8 @@
},
"license": "BSD-2-Clause",
"dependencies": {
- "node-pre-gyp": "^0.6.28"
+ "node-pre-gyp": "^0.6.28",
+ "nan": "^2.4.0"
},
"devDependencies": {
"aws-sdk": "^2.3.5",
@@ -21,11 +22,11 @@
"ejs": "^2.4.1",
"express": "^4.11.1",
"lodash": "^4.16.4",
- "mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#98a56d538b11fb331aa67a6d632d6ecd6821b007",
- "mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#7f62a4fc9f21e619824d68abbc4b03cbc1685572",
- "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#af9ee275f19e81f839a2733e6906c3fac272620e",
+ "mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#49e8b407bdbbe6f7c92dbcb56d3d51f425fc2653",
"mkdirp": "^0.5.1",
"node-cmake": "^1.2.1",
+ "pixelmatch": "^4.0.2",
+ "pngjs": "^3.0.0",
"request": "^2.72.0",
"tape": "^4.5.1"
},
@@ -47,4 +48,4 @@
"remote_path": "./{name}/v{version}",
"package_name": "{node_abi}-{platform}-{arch}.tar.gz"
}
-}
+} \ No newline at end of file
diff --git a/platform/android/.gitignore b/platform/android/.gitignore
index b0e8cceb45..81eeaad167 100644
--- a/platform/android/.gitignore
+++ b/platform/android/.gitignore
@@ -30,5 +30,5 @@ fabric.properties
captures/
# Generated test cases
-MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/activity/gen/
+MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/
diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md
index 836e1da7ae..b89e498d21 100644
--- a/platform/android/CHANGELOG.md
+++ b/platform/android/CHANGELOG.md
@@ -2,6 +2,62 @@
Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started.
+## 5.0.0 - TBA
+
+<<<<<<< HEAD
+* Consistent double tap zoom acceleration [#7514](https://github.com/mapbox/mapbox-gl-native/issues/7514)
+* Cleanup inconsistencies float vs double [#4445](https://github.com/mapbox/mapbox-gl-native/issues/4445)
+* Add `mapbox_` prefix to attributes [#6482](https://github.com/mapbox/mapbox-gl-native/issues/6482)
+* Update LOST to 2.0.0 [#6573](https://github.com/mapbox/mapbox-gl-native/issues/6537)
+* Support for Android Nougat [#5910](5910-move-listener-logic-for-nougat)
+ - move location listening logic to onStart/onStop Activity lifecylce methods
+* Removal of accesstoken on MapView and MapboxMap [#5621](https://github.com/mapbox/mapbox-gl-native/issues/5621)
+* Introduction of new make targets [#5940](https://github.com/mapbox/mapbox-gl-native/issues/5940)
+ - Targets for testing, running and using external tools directly from the commandline
+* Cleanup gradle files [#6009](https://github.com/mapbox/mapbox-gl-native/issues/6009)
+ - Introducing single purpose .gradle files
+* Checkstyle integration [#7442](https://github.com/mapbox/mapbox-gl-native/pull/7442)
+* Transform refactor [#6532](https://github.com/mapbox/mapbox-gl-native/issues/6532)
+ - All camera related code is moved to a dedicated transfrom class cfr. core architecture
+* Encapsulate Gestures [#6557](https://github.com/mapbox/mapbox-gl-native/issues/6557)
+ - All gesture event code is encapsulated in MapGestureDetector
+ - All key event code is encapsulated in MapKeyListener
+* Transparent background for MyLocationView [#7116](https://github.com/mapbox/mapbox-gl-native/issues/7116)
+* Update documentation on generate sanity tests [#7147](https://github.com/mapbox/mapbox-gl-native/issues/7147)
+* Update documentation on style templates [#7157](https://github.com/mapbox/mapbox-gl-native/issues/7157)
+* NullPointerException during save instance state [#7157](https://github.com/mapbox/mapbox-gl-native/issues/7157)
+* Move management style to core [#7275](https://github.com/mapbox/mapbox-gl-native/issues/7275)
+* OnCameraChange not called for the final position of animation bug [#7350](https://github.com/mapbox/mapbox-gl-native/issues/7350)
+* MapboxAccountManager refactor [#6534](https://github.com/mapbox/mapbox-gl-native/issues/6534)
+ - Consolidating the location where tokens are set
+ - Rename to reflect the increased responsibilities introduced in prior releases
+* AnnotationManager refactor [#6067](https://github.com/mapbox/mapbox-gl-native/issues/6067)
+ - Extracting all business logic related to annotations into a seperate class cfr. to core and the iOS codebase
+* Gesture handling bugs
+ - Avoid calls to onFling when while pinch zooming [#7666](https://github.com/mapbox/mapbox-gl-native/issues/7666)
+
+## 4.2.1 - December 22, 2016
+
+Mapbox Android 4.2.1 is a bugfix release build on top of 4.2.0 and resolves:
+
+* Gesture handling bugs
+ - Reverse fling when tilted [#7383](https://github.com/mapbox/mapbox-gl-native/pull/7383)
+ - Rotation is hard trigger [#7299](https://github.com/mapbox/mapbox-gl-native/pull/7299)
+* Null pointer exception on TrackingSettings [#7505](https://github.com/mapbox/mapbox-gl-native/pull/7505)
+* Patches to our CI integration [#7363](https://github.com/mapbox/mapbox-gl-native/pull/7363) & [#7385](https://github.com/mapbox/mapbox-gl-native/pull/7385)
+* Screen density is now correctly applied for attributes [#7327](https://github.com/mapbox/mapbox-gl-native/pull/7327)
+* Usage of LocalBroadCastReceiver [#7511](https://github.com/mapbox/mapbox-gl-native/pull/7511)
+
+## 4.2.0 - December 14, 2016
+
+Mapbox Android 4.2.0 contains all 4.2.0-beta.3 changes and adds:
+
+* Adds additional documentation to APIs
+* Resolved issue with marker views occasionally not showing up until a gesture was performed on map [#7239](https://github.com/mapbox/mapbox-gl-native/pull/7239)
+* Added horizontal accuracy to location events [#7237](https://github.com/mapbox/mapbox-gl-native/pull/7237)
+* Resolved issue with changing visibility of a layer [#7242](https://github.com/mapbox/mapbox-gl-native/pull/7242)
+* Proguard improvement and fixes
+
## 4.2.0-beta.3 - September 21, 2016
Mapbox Android 4.2.0-beta.3 contains all 4.2.0-beta.2 changes and adds:
diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle
index 8e8c25ba66..ae02f8765c 100644
--- a/platform/android/MapboxGLAndroidSDK/build.gradle
+++ b/platform/android/MapboxGLAndroidSDK/build.gradle
@@ -1,35 +1,19 @@
-apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.library'
-apply plugin: 'checkstyle'
-apply plugin: 'maven'
-apply plugin: 'signing'
-
-allprojects {
- group project.GROUP
- version project.VERSION_NAME
-
- repositories {
- mavenCentral()
- }
-}
-
-repositories {
- mavenCentral()
-}
ext {
- supportLibVersion = '23.4.0'
+ supportLibVersion = '25.1.0'
}
dependencies {
compile "com.android.support:support-annotations:${supportLibVersion}"
compile "com.android.support:support-v4:${supportLibVersion}"
compile "com.android.support:design:${supportLibVersion}"
- compile 'com.squareup.okhttp3:okhttp:3.3.0'
- compile 'com.mapzen.android:lost:1.1.1'
+ compile 'com.squareup.okhttp3:okhttp:3.5.0'
+ compile 'com.mapzen.android:lost:2.0.0'
+ compile 'com.jakewharton.timber:timber:4.3.1'
- // Mapbox Android Services
- compile('com.mapbox.mapboxsdk:mapbox-java-services:1.3.1@jar') {
+ // Mapbox Android Services (GeoJSON support)
+ compile('com.mapbox.mapboxsdk:mapbox-java-geojson:2.0.0-SNAPSHOT@jar') {
transitive = true
}
}
@@ -46,7 +30,13 @@ android {
buildConfigField "String", "GIT_REVISION_SHORT", String.format("\"%s\"", getGitRevision())
}
+ android {
+ // avoid naming conflicts, force usage of prefix
+ resourcePrefix 'mapbox_'
+ }
+
sourceSets {
+ // limit amount of exposed library resources
main.res.srcDirs += 'src/main/res-public'
}
@@ -70,94 +60,13 @@ android {
}
release {
- jniDebuggable false
+ // aar proguard configuration
consumerProguardFiles 'proguard-rules.pro'
+ jniDebuggable false
}
}
}
-configurations {
- all*.exclude group: 'commons-logging', module: 'commons-logging'
- all*.exclude group: 'commons-collections', module: 'commons-collections'
-}
-
-android.libraryVariants.all { variant ->
- def name = variant.name
- //noinspection GroovyAssignabilityCheck
- task "javadoc$name"(type: Javadoc) {
- description = "Generates javadoc for build $name"
- failOnError = false
- destinationDir = new File(destinationDir, variant.baseName)
- source = files(variant.javaCompile.source)
- classpath = files(variant.javaCompile.classpath.files) + files(android.bootClasspath)
- options.windowTitle("Mapbox Android SDK $VERSION_NAME Reference")
- options.docTitle("Mapbox Android SDK $VERSION_NAME")
- options.header("Mapbox Android SDK $VERSION_NAME Reference")
- options.bottom("&copy; 2015&ndash;2017 Mapbox. All rights reserved.")
- options.links("http://docs.oracle.com/javase/7/docs/api/")
- options.linksOffline("http://d.android.com/reference/", "$System.env.ANDROID_HOME/docs/reference")
- options.overview("src/main/java/overview.html")
- options.group("Mapbox Android SDK", "com.mapbox.*")
- options.group("Third Party Libraries", "com.almeros.*")
- exclude '**/R.java', '**/BuildConfig.java', 'com/almeros/**'
- }
-}
-
-/*
-task cleanJNIBuilds {
- def jniLibsDir = new File("MapboxGLAndroidSDK/src/main/jniLibs")
- delete jniLibsDir.absolutePath
-}
-*/
-
-android.libraryVariants.all { variant ->
- def name = variant.buildType.name
- def checkstyle = project.tasks.create "checkstyle${name.capitalize()}", Checkstyle
- checkstyle.dependsOn variant.javaCompile
- checkstyle.source variant.javaCompile.source
- checkstyle.classpath = project.fileTree(variant.javaCompile.destinationDir)
- checkstyle.exclude('**/BuildConfig.java')
- checkstyle.exclude('**/R.java')
- checkstyle.exclude('**/com/almeros/android/multitouch/**')
- project.tasks.getByName("check").dependsOn checkstyle
-}
-
-// From https://raw.github.com/mcxiaoke/gradle-mvn-push/master/jar.gradle
-android.libraryVariants.all { variant ->
- def jarTask = project.tasks.create(name: "jar${variant.name.capitalize()}", type: Jar) {
- from variant.javaCompile.destinationDir
- exclude "**/R.class"
- exclude "**/BuildConfig.class"
- }
- jarTask.dependsOn variant.javaCompile
- artifacts.add('archives', jarTask);
-}
-
-// From https://raw.github.com/mcxiaoke/gradle-mvn-push/master/gradle-mvn-push.gradle
-def isReleaseBuild() {
- return VERSION_NAME.contains("SNAPSHOT") == false
-}
-
-def getReleaseRepositoryUrl() {
- return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL :
- "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
-}
-
-def getSnapshotRepositoryUrl() {
- return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL :
- "https://oss.sonatype.org/content/repositories/snapshots/"
-}
-
-def getRepositoryUsername() {
- return hasProperty('USERNAME') ? USERNAME :
- (hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "")
-}
-
-def getRepositoryPassword() {
- return hasProperty('PASSWORD') ? PASSWORD :
- (hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "")
-}
-
def getGitRevision() {
def cmd = "git rev-parse --short HEAD"
def proc = cmd.execute()
@@ -165,121 +74,11 @@ def getGitRevision() {
return ref
}
-task apklib(type: Zip) {
- appendix = extension = 'apklib'
-
- from 'AndroidManifest.xml'
- into('res') {
- from 'res'
- }
- into('src') {
- from 'src'
- }
-}
-
-artifacts {
- archives apklib
-}
-
-afterEvaluate { project ->
- uploadArchives {
- repositories {
- mavenDeployer {
- beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
-
- pom.groupId = GROUP
- pom.artifactId = POM_ARTIFACT_ID
- pom.version = VERSION_NAME
-
- repository(url: getReleaseRepositoryUrl()) {
- authentication(userName: getRepositoryUsername(),
- password: getRepositoryPassword())
- }
- snapshotRepository(url: getSnapshotRepositoryUrl()) {
- authentication(userName: getRepositoryUsername(),
- password: getRepositoryPassword())
- }
-
-/*
- // Leaving out as artifact was incorrectly named when found
- addFilter('aar') { artifact, file ->
- artifact.name == archivesBaseName
- }
- addFilter('apklib') { artifact, file ->
- artifact.name == archivesBaseName + '-apklib'
- }
-*/
-
- pom.project {
- name POM_NAME
- packaging POM_PACKAGING
- description POM_DESCRIPTION
- url POM_URL
-
- scm {
- url POM_SCM_URL
- connection POM_SCM_CONNECTION
- developerConnection POM_SCM_DEV_CONNECTION
- }
-
- licenses {
- license {
- name POM_LICENCE_NAME
- url POM_LICENCE_URL
- distribution POM_LICENCE_DIST
- }
- }
-
- developers {
- developer {
- id POM_DEVELOPER_ID
- name POM_DEVELOPER_NAME
- }
- }
- }
- }
- }
- }
-
- signing {
- required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
- sign configurations.archives
- }
-
- task androidJavadocs(type: Javadoc) {
- source = android.sourceSets.main.java.sourceFiles
- classpath = files(android.bootClasspath)
- }
-
- task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
- classifier = 'javadoc'
- from androidJavadocs.destinationDir
- }
-
- task androidSourcesJar(type: Jar) {
- classifier = 'sources'
- from android.sourceSets.main.java.sourceFiles
- }
-
- artifacts {
- archives androidSourcesJar
- archives androidJavadocsJar
- }
-}
-
-
-task makeClean(type: Exec) {
- workingDir '../../'
- commandLine 'make', 'clean'
-}
-
-task makeAndroid(type: Exec) {
- workingDir '../../'
- commandLine 'make', 'android'
-}
-
-task makeAndroidAll(type: Exec) {
- workingDir '../../'
- commandLine 'make', 'apackage'
+configurations {
+ all*.exclude group: 'commons-logging', module: 'commons-logging'
+ all*.exclude group: 'commons-collections', module: 'commons-collections'
}
+apply from: 'gradle-javadoc.gradle'
+apply from: 'gradle-publish.gradle'
+apply from: 'gradle-checkstyle.gradle' \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/deploy.sh b/platform/android/MapboxGLAndroidSDK/deploy.sh
deleted file mode 100755
index c9392201e4..0000000000
--- a/platform/android/MapboxGLAndroidSDK/deploy.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/usr/bin/env bash
-../gradlew -b build.gradle clean assembleRelease uploadArchives
diff --git a/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle b/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle
new file mode 100644
index 0000000000..cdcc7f1e23
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle
@@ -0,0 +1,17 @@
+apply plugin: 'checkstyle'
+
+checkstyle {
+ toolVersion = "7.1.1" // 7.3
+ configFile = "../checkstyle.xml" as File
+}
+
+task checkstyle(type: Checkstyle) {
+ description 'Checks if the code adheres to coding standards'
+ group 'verification'
+ configFile file("../checkstyle.xml")
+ source 'src'
+ include '**/*.java'
+ exclude '**/gen/**'
+ classpath = files()
+ ignoreFailures = false
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/gradle-javadoc.gradle b/platform/android/MapboxGLAndroidSDK/gradle-javadoc.gradle
new file mode 100644
index 0000000000..ba7601127c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/gradle-javadoc.gradle
@@ -0,0 +1,21 @@
+android.libraryVariants.all { variant ->
+ def name = variant.name
+ //noinspection GroovyAssignabilityCheck
+ task "javadoc$name"(type: Javadoc) {
+ description = "Generates javadoc for build $name"
+ failOnError = false
+ destinationDir = new File(destinationDir, variant.baseName)
+ source = files(variant.javaCompile.source)
+ classpath = files(variant.javaCompile.classpath.files) + files(android.bootClasspath)
+ options.windowTitle("Mapbox Android SDK $VERSION_NAME Reference")
+ options.docTitle("Mapbox Android SDK $VERSION_NAME")
+ options.header("Mapbox Android SDK $VERSION_NAME Reference")
+ options.bottom("&copy; 2015&ndash;2017 Mapbox. All rights reserved.")
+ options.links("http://docs.oracle.com/javase/7/docs/api/")
+ options.linksOffline("http://d.android.com/reference/", "$System.env.ANDROID_HOME/docs/reference")
+ options.overview("src/main/java/overview.html")
+ options.group("Mapbox Android SDK", "com.mapbox.*")
+ options.group("Third Party Libraries", "com.almeros.*")
+ exclude '**/R.java', '**/BuildConfig.java', 'com/almeros/**'
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/gradle-publish.gradle b/platform/android/MapboxGLAndroidSDK/gradle-publish.gradle
new file mode 100644
index 0000000000..f017434fac
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/gradle-publish.gradle
@@ -0,0 +1,153 @@
+apply plugin: 'maven'
+apply plugin: 'signing'
+
+allprojects {
+ group project.GROUP
+ version project.VERSION_NAME
+
+ repositories {
+ mavenCentral()
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+// From https://raw.github.com/mcxiaoke/gradle-mvn-push/master/jar.gradle
+android.libraryVariants.all { variant ->
+ def jarTask = project.tasks.create(name: "jar${variant.name.capitalize()}", type: Jar) {
+ from variant.javaCompile.destinationDir
+ exclude "**/R.class"
+ exclude "**/BuildConfig.class"
+ }
+ jarTask.dependsOn variant.javaCompile
+ artifacts.add('archives', jarTask);
+}
+
+// From https://raw.github.com/mcxiaoke/gradle-mvn-push/master/gradle-mvn-push.gradle
+def isReleaseBuild() {
+ return VERSION_NAME.contains("SNAPSHOT") == false
+}
+
+def getReleaseRepositoryUrl() {
+ return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL :
+ "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
+}
+
+def getSnapshotRepositoryUrl() {
+ return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL :
+ "https://oss.sonatype.org/content/repositories/snapshots/"
+}
+
+def getRepositoryUsername() {
+ return hasProperty('USERNAME') ? USERNAME :
+ (hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "")
+}
+
+def getRepositoryPassword() {
+ return hasProperty('PASSWORD') ? PASSWORD :
+ (hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "")
+}
+
+task apklib(type: Zip) {
+ appendix = extension = 'apklib'
+
+ from 'AndroidManifest.xml'
+ into('res') {
+ from 'res'
+ }
+ into('src') {
+ from 'src'
+ }
+}
+
+artifacts {
+ archives apklib
+}
+
+afterEvaluate { project ->
+ uploadArchives {
+ repositories {
+ mavenDeployer {
+ beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
+
+ pom.groupId = GROUP
+ pom.artifactId = POM_ARTIFACT_ID
+ pom.version = VERSION_NAME
+
+ repository(url: getReleaseRepositoryUrl()) {
+ authentication(userName: getRepositoryUsername(),
+ password: getRepositoryPassword())
+ }
+ snapshotRepository(url: getSnapshotRepositoryUrl()) {
+ authentication(userName: getRepositoryUsername(),
+ password: getRepositoryPassword())
+ }
+
+/*
+ // Leaving out as artifact was incorrectly named when found
+ addFilter('aar') { artifact, file ->
+ artifact.name == archivesBaseName
+ }
+ addFilter('apklib') { artifact, file ->
+ artifact.name == archivesBaseName + '-apklib'
+ }
+*/
+
+ pom.project {
+ name POM_NAME
+ packaging POM_PACKAGING
+ description POM_DESCRIPTION
+ url POM_URL
+
+ scm {
+ url POM_SCM_URL
+ connection POM_SCM_CONNECTION
+ developerConnection POM_SCM_DEV_CONNECTION
+ }
+
+ licenses {
+ license {
+ name POM_LICENCE_NAME
+ url POM_LICENCE_URL
+ distribution POM_LICENCE_DIST
+ }
+ }
+
+ developers {
+ developer {
+ id POM_DEVELOPER_ID
+ name POM_DEVELOPER_NAME
+ }
+ }
+ }
+ }
+ }
+ }
+
+ signing {
+ required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
+ sign configurations.archives
+ }
+
+ task androidJavadocs(type: Javadoc) {
+ source = android.sourceSets.main.java.sourceFiles
+ classpath = files(android.bootClasspath)
+ }
+
+ task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
+ classifier = 'javadoc'
+ from androidJavadocs.destinationDir
+ }
+
+ task androidSourcesJar(type: Jar) {
+ classifier = 'sources'
+ from android.sourceSets.main.java.sourceFiles
+ }
+
+ artifacts {
+ archives androidSourcesJar
+ archives androidJavadocsJar
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties
index 6aab985298..7bdc7ab455 100644
--- a/platform/android/MapboxGLAndroidSDK/gradle.properties
+++ b/platform/android/MapboxGLAndroidSDK/gradle.properties
@@ -1,5 +1,5 @@
GROUP=com.mapbox.mapboxsdk
-VERSION_NAME=4.2.0-SNAPSHOT
+VERSION_NAME=5.0.0-SNAPSHOT
POM_DESCRIPTION=Mapbox GL Android SDK
POM_URL=https://github.com/mapbox/mapbox-gl-native
@@ -13,9 +13,9 @@ POM_DEVELOPER_ID=mapbox
POM_DEVELOPER_NAME=Mapbox
ANDROID_MIN_SDK=15
-ANDROID_BUILD_TARGET_SDK_VERSION=23
-ANDROID_BUILD_TOOLS_VERSION=23.0.3
-ANDROID_BUILD_SDK_VERSION=23
+ANDROID_BUILD_TARGET_SDK_VERSION=25
+ANDROID_BUILD_TOOLS_VERSION=25.0.2
+ANDROID_BUILD_SDK_VERSION=25
POM_NAME=Mapbox Android SDK
POM_ARTIFACT_ID=mapbox-android-sdk
diff --git a/platform/android/MapboxGLAndroidSDK/proguard-rules.pro b/platform/android/MapboxGLAndroidSDK/proguard-rules.pro
index 96f7bb95f3..92ef05df68 100644
--- a/platform/android/MapboxGLAndroidSDK/proguard-rules.pro
+++ b/platform/android/MapboxGLAndroidSDK/proguard-rules.pro
@@ -5,6 +5,7 @@
# Square okio, ignoring warnings,
# see https://github.com/square/okio/issues/60
+-dontwarn okhttp3.**
-dontwarn okio.**
# Gesture package
@@ -38,7 +39,48 @@
# Package telemetry
-keep class com.mapbox.mapboxsdk.telemetry.** { *; }
-# Keep external project mapbox-java,
-# Needs to be removed after https://github.com/mapbox/mapbox-java/issues/178 is resolved
--keep class com.mapbox.services.** { *; }
+#
+# Mapbox-java Proguard rules
+# We include these rules since libjava is a Jar file not AAR
+#
+# Retrofit 2
+# Platform calls Class.forName on types which do not exist on Android to determine platform.
+-dontnote retrofit2.Platform
+# Platform used when running on RoboVM on iOS. Will not be used at runtime.
+-dontnote retrofit2.Platform$IOS$MainThreadExecutor
+# Platform used when running on Java 8 VMs. Will not be used at runtime.
+-dontwarn retrofit2.Platform$Java8
+# Retain generic type information for use by reflection by converters and adapters.
+-keepattributes Signature
+# Retain declared checked exceptions for use by a Proxy instance.
+-keepattributes Exceptions
+
+# For using GSON @Expose annotation
+-keepattributes *Annotation*
+# Gson specific classes
+-dontwarn sun.misc.**
+
+# Prevent proguard from stripping interface information from TypeAdapterFactory,
+# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
+-keep class * implements com.google.gson.TypeAdapterFactory
+-keep class * implements com.google.gson.JsonSerializer
+-keep class * implements com.google.gson.JsonDeserializer
+
+# MAS Data Models
+-keep class com.mapbox.services.commons.geojson.** { *; }
+-keep class com.mapbox.services.mapmatching.v4.models.** { *; }
+-keep class com.mapbox.services.distance.v1.models.** { *; }
+-keep class com.mapbox.services.directions.v4.models.** { *; }
+-keep class com.mapbox.services.directions.v5.models.** { *; }
+-keep class com.mapbox.services.geocoding.v5.models.** { *; }
+
+-dontwarn javax.annotation.**
+
+-keepclassmembers class rx.internal.util.unsafe.** {
+ long producerIndex;
+ long consumerIndex;
+}
+
+-keep class com.google.** { *; }
+-dontwarn com.google.** \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/BaseGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/BaseGestureDetector.java
index 622e8f759c..b7bcb925a1 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/BaseGestureDetector.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/BaseGestureDetector.java
@@ -6,19 +6,19 @@ import android.view.MotionEvent;
/**
* @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie
* (code.almeros.com)
- *
+ * <p>
* All rights reserved.
- *
+ * <p>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ * <p>
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ * <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -33,129 +33,128 @@ import android.view.MotionEvent;
* POSSIBILITY OF SUCH DAMAGE.
*/
public abstract class BaseGestureDetector {
- protected final Context mContext;
- protected boolean mGestureInProgress;
-
- protected MotionEvent mPrevEvent;
- protected MotionEvent mCurrEvent;
-
- protected float mCurrPressure;
- protected float mPrevPressure;
- protected long mTimeDelta;
-
- /**
- * This value is the threshold ratio between the previous combined pressure
- * and the current combined pressure. When pressure decreases rapidly
- * between events the position values can often be imprecise, as it usually
- * indicates that the user is in the process of lifting a pointer off of the
- * device. This value was tuned experimentally.
- */
- protected static final float PRESSURE_THRESHOLD = 0.67f;
-
- public BaseGestureDetector(Context context) {
- mContext = context;
+ protected final Context context;
+ protected boolean gestureInProgress;
+
+ protected MotionEvent prevEvent;
+ protected MotionEvent currEvent;
+
+ protected float currPressure;
+ protected float prevPressure;
+ protected long timeDelta;
+
+ /**
+ * This value is the threshold ratio between the previous combined pressure
+ * and the current combined pressure. When pressure decreases rapidly
+ * between events the position values can often be imprecise, as it usually
+ * indicates that the user is in the process of lifting a pointer off of the
+ * device. This value was tuned experimentally.
+ */
+ protected static final float PRESSURE_THRESHOLD = 0.67f;
+
+ public BaseGestureDetector(Context context) {
+ this.context = context;
+ }
+
+ /**
+ * All gesture detectors need to be called through this method to be able to
+ * detect gestures. This method delegates work to handler methods
+ * (handleStartProgressEvent, handleInProgressEvent) implemented in
+ * extending classes.
+ *
+ * @param event MotionEvent
+ * @return {@code true} as handled
+ */
+ public boolean onTouchEvent(MotionEvent event) {
+ final int actionCode = event.getAction() & MotionEvent.ACTION_MASK;
+ if (!gestureInProgress) {
+ handleStartProgressEvent(actionCode, event);
+ } else {
+ handleInProgressEvent(actionCode, event);
}
-
- /**
- * All gesture detectors need to be called through this method to be able to
- * detect gestures. This method delegates work to handler methods
- * (handleStartProgressEvent, handleInProgressEvent) implemented in
- * extending classes.
- *
- * @param event MotionEvent
- * @return {@code true} as handled
- */
- public boolean onTouchEvent(MotionEvent event) {
- final int actionCode = event.getAction() & MotionEvent.ACTION_MASK;
- if (!mGestureInProgress) {
- handleStartProgressEvent(actionCode, event);
- } else {
- handleInProgressEvent(actionCode, event);
- }
- return true;
- }
-
- /**
- * Called when the current event occurred when NO gesture is in progress
- * yet. The handling in this implementation may set the gesture in progress
- * (via mGestureInProgress) or out of progress
- *
- * @param actionCode Action Code from MotionEvent
- * @param event MotionEvent
- */
- protected abstract void handleStartProgressEvent(int actionCode,
- MotionEvent event);
-
- /**
- * Called when the current event occurred when a gesture IS in progress. The
- * handling in this implementation may set the gesture out of progress (via
- * mGestureInProgress).
- *
- *
- * @param actionCode Action Code from MotionEvent
- * @param event MotionEvent
- */
- protected abstract void handleInProgressEvent(int actionCode,
- MotionEvent event);
-
- protected void updateStateByEvent(MotionEvent curr) {
- final MotionEvent prev = mPrevEvent;
-
- // Reset mCurrEvent
- if (mCurrEvent != null) {
- mCurrEvent.recycle();
- mCurrEvent = null;
- }
- mCurrEvent = MotionEvent.obtain(curr);
-
- // Delta time
- mTimeDelta = curr.getEventTime() - prev.getEventTime();
-
- // Pressure
- mCurrPressure = curr.getPressure(curr.getActionIndex());
- mPrevPressure = prev.getPressure(prev.getActionIndex());
+ return true;
+ }
+
+ /**
+ * Called when the current event occurred when NO gesture is in progress
+ * yet. The handling in this implementation may set the gesture in progress
+ * (via gestureInProgress) or out of progress
+ *
+ * @param actionCode Action Code from MotionEvent
+ * @param event MotionEvent
+ */
+ protected abstract void handleStartProgressEvent(int actionCode,
+ MotionEvent event);
+
+ /**
+ * Called when the current event occurred when a gesture IS in progress. The
+ * handling in this implementation may set the gesture out of progress (via
+ * gestureInProgress).
+ *
+ * @param actionCode Action Code from MotionEvent
+ * @param event MotionEvent
+ */
+ protected abstract void handleInProgressEvent(int actionCode,
+ MotionEvent event);
+
+ protected void updateStateByEvent(MotionEvent curr) {
+ final MotionEvent prev = prevEvent;
+
+ // Reset currEvent
+ if (currEvent != null) {
+ currEvent.recycle();
+ currEvent = null;
}
+ currEvent = MotionEvent.obtain(curr);
- protected void resetState() {
- if (mPrevEvent != null) {
- mPrevEvent.recycle();
- mPrevEvent = null;
- }
- if (mCurrEvent != null) {
- mCurrEvent.recycle();
- mCurrEvent = null;
- }
- mGestureInProgress = false;
- }
+ // Delta time
+ timeDelta = curr.getEventTime() - prev.getEventTime();
- /**
- * Returns {@code true} if a gesture is currently in progress.
- *
- * @return {@code true} if a gesture is currently in progress, {@code false}
- * otherwise.
- */
- public boolean isInProgress() {
- return mGestureInProgress;
- }
+ // Pressure
+ currPressure = curr.getPressure(curr.getActionIndex());
+ prevPressure = prev.getPressure(prev.getActionIndex());
+ }
- /**
- * Return the time difference in milliseconds between the previous accepted
- * GestureDetector event and the current GestureDetector event.
- *
- * @return Time difference since the last move event in milliseconds.
- */
- public long getTimeDelta() {
- return mTimeDelta;
+ protected void resetState() {
+ if (prevEvent != null) {
+ prevEvent.recycle();
+ prevEvent = null;
}
-
- /**
- * Return the event time of the current GestureDetector event being
- * processed.
- *
- * @return Current GestureDetector event time in milliseconds.
- */
- public long getEventTime() {
- return mCurrEvent.getEventTime();
+ if (currEvent != null) {
+ currEvent.recycle();
+ currEvent = null;
}
+ gestureInProgress = false;
+ }
+
+ /**
+ * Returns {@code true} if a gesture is currently in progress.
+ *
+ * @return {@code true} if a gesture is currently in progress, {@code false}
+ * otherwise.
+ */
+ public boolean isInProgress() {
+ return gestureInProgress;
+ }
+
+ /**
+ * Return the time difference in milliseconds between the previous accepted
+ * GestureDetector event and the current GestureDetector event.
+ *
+ * @return Time difference since the last move event in milliseconds.
+ */
+ public long getTimeDelta() {
+ return timeDelta;
+ }
+
+ /**
+ * Return the event time of the current GestureDetector event being
+ * processed.
+ *
+ * @return Current GestureDetector event time in milliseconds.
+ */
+ public long getEventTime() {
+ return currEvent.getEventTime();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/MoveGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/MoveGestureDetector.java
index 2430f3f920..bc7dda6159 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/MoveGestureDetector.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/MoveGestureDetector.java
@@ -7,19 +7,19 @@ import android.view.MotionEvent;
/**
* @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie
* (code.almeros.com)
- *
+ * <p>
* All rights reserved.
- *
+ * <p>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ * <p>
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ * <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -35,151 +35,151 @@ import android.view.MotionEvent;
*/
public class MoveGestureDetector extends BaseGestureDetector {
- /**
- * Listener which must be implemented which is used by MoveGestureDetector
- * to perform callbacks to any implementing class which is registered to a
- * MoveGestureDetector via the constructor.
- *
- * @see MoveGestureDetector.SimpleOnMoveGestureListener
- */
- public interface OnMoveGestureListener {
- public boolean onMove(MoveGestureDetector detector);
-
- public boolean onMoveBegin(MoveGestureDetector detector);
-
- public void onMoveEnd(MoveGestureDetector detector);
+ /**
+ * Listener which must be implemented which is used by MoveGestureDetector
+ * to perform callbacks to any implementing class which is registered to a
+ * MoveGestureDetector via the constructor.
+ *
+ * @see MoveGestureDetector.SimpleOnMoveGestureListener
+ */
+ public interface OnMoveGestureListener {
+ public boolean onMove(MoveGestureDetector detector);
+
+ public boolean onMoveBegin(MoveGestureDetector detector);
+
+ public void onMoveEnd(MoveGestureDetector detector);
+ }
+
+ /**
+ * Helper class which may be extended and where the methods may be
+ * implemented. This way it is not necessary to implement all methods of
+ * OnMoveGestureListener.
+ */
+ public static class SimpleOnMoveGestureListener implements
+ OnMoveGestureListener {
+ public boolean onMove(MoveGestureDetector detector) {
+ return false;
}
- /**
- * Helper class which may be extended and where the methods may be
- * implemented. This way it is not necessary to implement all methods of
- * OnMoveGestureListener.
- */
- public static class SimpleOnMoveGestureListener implements
- OnMoveGestureListener {
- public boolean onMove(MoveGestureDetector detector) {
- return false;
- }
-
- public boolean onMoveBegin(MoveGestureDetector detector) {
- return true;
- }
+ public boolean onMoveBegin(MoveGestureDetector detector) {
+ return true;
+ }
- public void onMoveEnd(MoveGestureDetector detector) {
- // Do nothing, overridden implementation may be used
- }
+ public void onMoveEnd(MoveGestureDetector detector) {
+ // Do nothing, overridden implementation may be used
}
+ }
- private static final PointF FOCUS_DELTA_ZERO = new PointF();
+ private static final PointF FOCUS_DELTA_ZERO = new PointF();
- private final OnMoveGestureListener mListener;
+ private final OnMoveGestureListener listener;
- private PointF mFocusExternal = new PointF();
- private PointF mFocusDeltaExternal = new PointF();
+ private PointF focusExternal = new PointF();
+ private PointF focusDeltaExternal = new PointF();
- public MoveGestureDetector(Context context, OnMoveGestureListener listener) {
- super(context);
- mListener = listener;
- }
+ public MoveGestureDetector(Context context, OnMoveGestureListener listener) {
+ super(context);
+ this.listener = listener;
+ }
- @Override
- protected void handleStartProgressEvent(int actionCode, MotionEvent event) {
- switch (actionCode) {
- case MotionEvent.ACTION_DOWN:
- resetState(); // In case we missed an UP/CANCEL event
+ @Override
+ protected void handleStartProgressEvent(int actionCode, MotionEvent event) {
+ switch (actionCode) {
+ case MotionEvent.ACTION_DOWN:
+ resetState(); // In case we missed an UP/CANCEL event
- mPrevEvent = MotionEvent.obtain(event);
- mTimeDelta = 0;
+ prevEvent = MotionEvent.obtain(event);
+ timeDelta = 0;
- updateStateByEvent(event);
- break;
+ updateStateByEvent(event);
+ break;
- case MotionEvent.ACTION_MOVE:
- mGestureInProgress = mListener.onMoveBegin(this);
- break;
- }
+ case MotionEvent.ACTION_MOVE:
+ gestureInProgress = listener.onMoveBegin(this);
+ break;
}
-
- @Override
- protected void handleInProgressEvent(int actionCode, MotionEvent event) {
- switch (actionCode) {
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- mListener.onMoveEnd(this);
- resetState();
- break;
-
- case MotionEvent.ACTION_MOVE:
- updateStateByEvent(event);
-
- // Only accept the event if our relative pressure is within
- // a certain limit. This can help filter shaky data as a
- // finger is lifted.
- if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) {
- final boolean updatePrevious = mListener.onMove(this);
- if (updatePrevious) {
- mPrevEvent.recycle();
- mPrevEvent = MotionEvent.obtain(event);
- }
- }
- break;
+ }
+
+ @Override
+ protected void handleInProgressEvent(int actionCode, MotionEvent event) {
+ switch (actionCode) {
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ listener.onMoveEnd(this);
+ resetState();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ updateStateByEvent(event);
+
+ // Only accept the event if our relative pressure is within
+ // a certain limit. This can help filter shaky data as a
+ // finger is lifted.
+ if (currPressure / prevPressure > PRESSURE_THRESHOLD) {
+ final boolean updatePrevious = listener.onMove(this);
+ if (updatePrevious) {
+ prevEvent.recycle();
+ prevEvent = MotionEvent.obtain(event);
+ }
}
+ break;
}
-
- protected void updateStateByEvent(MotionEvent curr) {
- super.updateStateByEvent(curr);
-
- final MotionEvent prev = mPrevEvent;
-
- // Focus intenal
- PointF mCurrFocusInternal = determineFocalPoint(curr);
- PointF mPrevFocusInternal = determineFocalPoint(prev);
-
- // Focus external
- // - Prevent skipping of focus delta when a finger is added or removed
- boolean mSkipNextMoveEvent = prev.getPointerCount() != curr
- .getPointerCount();
- mFocusDeltaExternal = mSkipNextMoveEvent ? FOCUS_DELTA_ZERO
- : new PointF(mCurrFocusInternal.x - mPrevFocusInternal.x,
- mCurrFocusInternal.y - mPrevFocusInternal.y);
-
- // - Don't directly use mFocusInternal (or skipping will occur). Add
- // unskipped delta values to mFocusExternal instead.
- mFocusExternal.x += mFocusDeltaExternal.x;
- mFocusExternal.y += mFocusDeltaExternal.y;
+ }
+
+ protected void updateStateByEvent(MotionEvent curr) {
+ super.updateStateByEvent(curr);
+
+ final MotionEvent prev = prevEvent;
+
+ // Focus intenal
+ PointF currFocusInternal = determineFocalPoint(curr);
+ PointF prevFocusInternal = determineFocalPoint(prev);
+
+ // Focus external
+ // - Prevent skipping of focus delta when a finger is added or removed
+ boolean skipNextMoveEvent = prev.getPointerCount() != curr
+ .getPointerCount();
+ focusDeltaExternal = skipNextMoveEvent ? FOCUS_DELTA_ZERO
+ : new PointF(currFocusInternal.x - prevFocusInternal.x,
+ currFocusInternal.y - prevFocusInternal.y);
+
+ // - Don't directly use mFocusInternal (or skipping will occur). Add
+ // unskipped delta values to focusExternal instead.
+ focusExternal.x += focusDeltaExternal.x;
+ focusExternal.y += focusDeltaExternal.y;
+ }
+
+ /**
+ * Determine (multi)finger focal point (a.k.a. center point between all
+ * fingers)
+ *
+ * @param motionEvent a {@link MotionEvent} object.
+ * @return PointF focal point
+ */
+ private PointF determineFocalPoint(MotionEvent motionEvent) {
+ // Number of fingers on screen
+ final int pCount = motionEvent.getPointerCount();
+ float x = 0.0f;
+ float y = 0.0f;
+
+ for (int i = 0; i < pCount; i++) {
+ x += motionEvent.getX(i);
+ y += motionEvent.getY(i);
}
- /**
- * Determine (multi)finger focal point (a.k.a. center point between all
- * fingers)
- *
- * @param e
- * @return PointF focal point
- */
- private PointF determineFocalPoint(MotionEvent e) {
- // Number of fingers on screen
- final int pCount = e.getPointerCount();
- float x = 0.0f;
- float y = 0.0f;
-
- for (int i = 0; i < pCount; i++) {
- x += e.getX(i);
- y += e.getY(i);
- }
-
- return new PointF(x / pCount, y / pCount);
- }
+ return new PointF(x / pCount, y / pCount);
+ }
- public float getFocusX() {
- return mFocusExternal.x;
- }
+ public float getFocusX() {
+ return focusExternal.x;
+ }
- public float getFocusY() {
- return mFocusExternal.y;
- }
+ public float getFocusY() {
+ return focusExternal.y;
+ }
- public PointF getFocusDelta() {
- return mFocusDeltaExternal;
- }
+ public PointF getFocusDelta() {
+ return focusDeltaExternal;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/RotateGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/RotateGestureDetector.java
index 124fe8509c..8c111a68df 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/RotateGestureDetector.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/RotateGestureDetector.java
@@ -6,19 +6,19 @@ import android.view.MotionEvent;
/**
* @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie
* (code.almeros.com)
- *
+ * <p>
* All rights reserved.
- *
+ * <p>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ * <p>
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ * <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -34,147 +34,147 @@ import android.view.MotionEvent;
*/
public class RotateGestureDetector extends TwoFingerGestureDetector {
- /**
- * Listener which must be implemented which is used by RotateGestureDetector
- * to perform callbacks to any implementing class which is registered to a
- * RotateGestureDetector via the constructor.
- *
- * @see RotateGestureDetector.SimpleOnRotateGestureListener
- */
- public interface OnRotateGestureListener {
- public boolean onRotate(RotateGestureDetector detector);
-
- public boolean onRotateBegin(RotateGestureDetector detector);
+ /**
+ * Listener which must be implemented which is used by RotateGestureDetector
+ * to perform callbacks to any implementing class which is registered to a
+ * RotateGestureDetector via the constructor.
+ *
+ * @see RotateGestureDetector.SimpleOnRotateGestureListener
+ */
+ public interface OnRotateGestureListener {
+ public boolean onRotate(RotateGestureDetector detector);
+
+ public boolean onRotateBegin(RotateGestureDetector detector);
+
+ public void onRotateEnd(RotateGestureDetector detector);
+ }
+
+ /**
+ * Helper class which may be extended and where the methods may be
+ * implemented. This way it is not necessary to implement all methods of
+ * OnRotateGestureListener.
+ */
+ public static class SimpleOnRotateGestureListener implements
+ OnRotateGestureListener {
+ public boolean onRotate(RotateGestureDetector detector) {
+ return false;
+ }
- public void onRotateEnd(RotateGestureDetector detector);
+ public boolean onRotateBegin(RotateGestureDetector detector) {
+ return true;
}
- /**
- * Helper class which may be extended and where the methods may be
- * implemented. This way it is not necessary to implement all methods of
- * OnRotateGestureListener.
- */
- public static class SimpleOnRotateGestureListener implements
- OnRotateGestureListener {
- public boolean onRotate(RotateGestureDetector detector) {
- return false;
+ public void onRotateEnd(RotateGestureDetector detector) {
+ // Do nothing, overridden implementation may be used
+ }
+ }
+
+ private final OnRotateGestureListener listener;
+ private boolean sloppyGesture;
+
+ public RotateGestureDetector(Context context,
+ OnRotateGestureListener listener) {
+ super(context);
+ this.listener = listener;
+ }
+
+ @Override
+ protected void handleStartProgressEvent(int actionCode, MotionEvent event) {
+ switch (actionCode) {
+ case MotionEvent.ACTION_POINTER_DOWN:
+ // At least the second finger is on screen now
+
+ resetState(); // In case we missed an UP/CANCEL event
+ prevEvent = MotionEvent.obtain(event);
+ timeDelta = 0;
+
+ updateStateByEvent(event);
+
+ // See if we have a sloppy gesture
+ sloppyGesture = isSloppyGesture(event);
+ if (!sloppyGesture) {
+ // No, start gesture now
+ gestureInProgress = listener.onRotateBegin(this);
}
+ break;
- public boolean onRotateBegin(RotateGestureDetector detector) {
- return true;
+ case MotionEvent.ACTION_MOVE:
+ if (!sloppyGesture) {
+ break;
}
- public void onRotateEnd(RotateGestureDetector detector) {
- // Do nothing, overridden implementation may be used
+ // See if we still have a sloppy gesture
+ sloppyGesture = isSloppyGesture(event);
+ if (!sloppyGesture) {
+ // No, start normal gesture now
+ gestureInProgress = listener.onRotateBegin(this);
}
- }
- private final OnRotateGestureListener mListener;
- private boolean mSloppyGesture;
+ break;
- public RotateGestureDetector(Context context,
- OnRotateGestureListener listener) {
- super(context);
- mListener = listener;
- }
-
- @Override
- protected void handleStartProgressEvent(int actionCode, MotionEvent event) {
- switch (actionCode) {
- case MotionEvent.ACTION_POINTER_DOWN:
- // At least the second finger is on screen now
-
- resetState(); // In case we missed an UP/CANCEL event
- mPrevEvent = MotionEvent.obtain(event);
- mTimeDelta = 0;
-
- updateStateByEvent(event);
-
- // See if we have a sloppy gesture
- mSloppyGesture = isSloppyGesture(event);
- if (!mSloppyGesture) {
- // No, start gesture now
- mGestureInProgress = mListener.onRotateBegin(this);
- }
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (!mSloppyGesture) {
- break;
- }
-
- // See if we still have a sloppy gesture
- mSloppyGesture = isSloppyGesture(event);
- if (!mSloppyGesture) {
- // No, start normal gesture now
- mGestureInProgress = mListener.onRotateBegin(this);
- }
-
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- if (!mSloppyGesture) {
- break;
- }
-
- break;
+ case MotionEvent.ACTION_POINTER_UP:
+ if (!sloppyGesture) {
+ break;
}
+
+ break;
}
+ }
- @Override
- protected void handleInProgressEvent(int actionCode, MotionEvent event) {
- switch (actionCode) {
- case MotionEvent.ACTION_POINTER_UP:
- // Gesture ended but
- updateStateByEvent(event);
-
- if (!mSloppyGesture) {
- mListener.onRotateEnd(this);
- }
-
- resetState();
- break;
-
- case MotionEvent.ACTION_CANCEL:
- if (!mSloppyGesture) {
- mListener.onRotateEnd(this);
- }
-
- resetState();
- break;
-
- case MotionEvent.ACTION_MOVE:
- updateStateByEvent(event);
-
- // Only accept the event if our relative pressure is within
- // a certain limit. This can help filter shaky data as a
- // finger is lifted.
- if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) {
- final boolean updatePrevious = mListener.onRotate(this);
- if (updatePrevious) {
- mPrevEvent.recycle();
- mPrevEvent = MotionEvent.obtain(event);
- }
- }
- break;
+ @Override
+ protected void handleInProgressEvent(int actionCode, MotionEvent event) {
+ switch (actionCode) {
+ case MotionEvent.ACTION_POINTER_UP:
+ // Gesture ended but
+ updateStateByEvent(event);
+
+ if (!sloppyGesture) {
+ listener.onRotateEnd(this);
}
- }
- @Override
- protected void resetState() {
- super.resetState();
- mSloppyGesture = false;
- }
+ resetState();
+ break;
- /**
- * Return the rotation difference from the previous rotate event to the
- * current event.
- *
- * @return The current rotation //difference in degrees.
- */
- public float getRotationDegreesDelta() {
- double diffRadians = Math.atan2(mPrevFingerDiffY, mPrevFingerDiffX)
- - Math.atan2(mCurrFingerDiffY, mCurrFingerDiffX);
- return (float) (diffRadians * 180.0 / Math.PI);
+ case MotionEvent.ACTION_CANCEL:
+ if (!sloppyGesture) {
+ listener.onRotateEnd(this);
+ }
+
+ resetState();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ updateStateByEvent(event);
+
+ // Only accept the event if our relative pressure is within
+ // a certain limit. This can help filter shaky data as a
+ // finger is lifted.
+ if (currPressure / prevPressure > PRESSURE_THRESHOLD) {
+ final boolean updatePrevious = listener.onRotate(this);
+ if (updatePrevious) {
+ prevEvent.recycle();
+ prevEvent = MotionEvent.obtain(event);
+ }
+ }
+ break;
}
+ }
+
+ @Override
+ protected void resetState() {
+ super.resetState();
+ sloppyGesture = false;
+ }
+
+ /**
+ * Return the rotation difference from the previous rotate event to the
+ * current event.
+ *
+ * @return The current rotation //difference in degrees.
+ */
+ public float getRotationDegreesDelta() {
+ double diffRadians = Math.atan2(prevFingerDiffY, prevFingerDiffX)
+ - Math.atan2(currFingerDiffY, currFingerDiffX);
+ return (float) (diffRadians * 180.0 / Math.PI);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/ShoveGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/ShoveGestureDetector.java
index 254597105b..9396578e48 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/ShoveGestureDetector.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/ShoveGestureDetector.java
@@ -5,21 +5,21 @@ import android.view.MotionEvent;
/**
* @author Robert Nordan (robert.nordan@norkart.no)
- *
+ * <p>
* Copyright (c) 2013, Norkart AS
- *
+ * <p>
* All rights reserved.
- *
+ * <p>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ * <p>
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ * <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -35,179 +35,180 @@ import android.view.MotionEvent;
*/
public class ShoveGestureDetector extends TwoFingerGestureDetector {
- /**
- * Listener which must be implemented which is used by ShoveGestureDetector
- * to perform callbacks to any implementing class which is registered to a
- * ShoveGestureDetector via the constructor.
- *
- * @see ShoveGestureDetector.SimpleOnShoveGestureListener
- */
- public interface OnShoveGestureListener {
- public boolean onShove(ShoveGestureDetector detector);
+ /**
+ * Listener which must be implemented which is used by ShoveGestureDetector
+ * to perform callbacks to any implementing class which is registered to a
+ * ShoveGestureDetector via the constructor.
+ *
+ * @see ShoveGestureDetector.SimpleOnShoveGestureListener
+ */
+ public interface OnShoveGestureListener {
+ public boolean onShove(ShoveGestureDetector detector);
+
+ public boolean onShoveBegin(ShoveGestureDetector detector);
+
+ public void onShoveEnd(ShoveGestureDetector detector);
+ }
+
+ /**
+ * Helper class which may be extended and where the methods may be
+ * implemented. This way it is not necessary to implement all methods of
+ * OnShoveGestureListener.
+ */
+ public static class SimpleOnShoveGestureListener implements
+ OnShoveGestureListener {
+ public boolean onShove(ShoveGestureDetector detector) {
+ return false;
+ }
- public boolean onShoveBegin(ShoveGestureDetector detector);
+ public boolean onShoveBegin(ShoveGestureDetector detector) {
+ return true;
+ }
- public void onShoveEnd(ShoveGestureDetector detector);
+ public void onShoveEnd(ShoveGestureDetector detector) {
+ // Do nothing, overridden implementation may be used
}
+ }
+
+ private float prevAverageY;
+ private float currAverageY;
+
+ private final OnShoveGestureListener listener;
+ private boolean sloppyGesture;
+
+ public ShoveGestureDetector(Context context, OnShoveGestureListener listener) {
+ super(context);
+ this.listener = listener;
+ }
- /**
- * Helper class which may be extended and where the methods may be
- * implemented. This way it is not necessary to implement all methods of
- * OnShoveGestureListener.
- */
- public static class SimpleOnShoveGestureListener implements
- OnShoveGestureListener {
- public boolean onShove(ShoveGestureDetector detector) {
- return false;
+ @Override
+ protected void handleStartProgressEvent(int actionCode, MotionEvent event) {
+ switch (actionCode) {
+ case MotionEvent.ACTION_POINTER_DOWN:
+ // At least the second finger is on screen now
+
+ resetState(); // In case we missed an UP/CANCEL event
+ prevEvent = MotionEvent.obtain(event);
+ timeDelta = 0;
+
+ updateStateByEvent(event);
+
+ // See if we have a sloppy gesture
+ sloppyGesture = isSloppyGesture(event);
+ if (!sloppyGesture) {
+ // No, start gesture now
+ gestureInProgress = listener.onShoveBegin(this);
}
+ break;
- public boolean onShoveBegin(ShoveGestureDetector detector) {
- return true;
+ case MotionEvent.ACTION_MOVE:
+ if (!sloppyGesture) {
+ break;
}
- public void onShoveEnd(ShoveGestureDetector detector) {
- // Do nothing, overridden implementation may be used
+ // See if we still have a sloppy gesture
+ sloppyGesture = isSloppyGesture(event);
+ if (!sloppyGesture) {
+ // No, start normal gesture now
+ gestureInProgress = listener.onShoveBegin(this);
}
- }
- private float mPrevAverageY;
- private float mCurrAverageY;
+ break;
- private final OnShoveGestureListener mListener;
- private boolean mSloppyGesture;
+ case MotionEvent.ACTION_POINTER_UP:
+ if (!sloppyGesture) {
+ break;
+ }
- public ShoveGestureDetector(Context context, OnShoveGestureListener listener) {
- super(context);
- mListener = listener;
+ break;
}
+ }
- @Override
- protected void handleStartProgressEvent(int actionCode, MotionEvent event) {
- switch (actionCode) {
- case MotionEvent.ACTION_POINTER_DOWN:
- // At least the second finger is on screen now
-
- resetState(); // In case we missed an UP/CANCEL event
- mPrevEvent = MotionEvent.obtain(event);
- mTimeDelta = 0;
-
- updateStateByEvent(event);
-
- // See if we have a sloppy gesture
- mSloppyGesture = isSloppyGesture(event);
- if (!mSloppyGesture) {
- // No, start gesture now
- mGestureInProgress = mListener.onShoveBegin(this);
- }
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (!mSloppyGesture) {
- break;
- }
-
- // See if we still have a sloppy gesture
- mSloppyGesture = isSloppyGesture(event);
- if (!mSloppyGesture) {
- // No, start normal gesture now
- mGestureInProgress = mListener.onShoveBegin(this);
- }
-
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- if (!mSloppyGesture) {
- break;
- }
-
- break;
- }
- }
+ @Override
+ protected void handleInProgressEvent(int actionCode, MotionEvent event) {
+ switch (actionCode) {
+ case MotionEvent.ACTION_POINTER_UP:
+ // Gesture ended but
+ updateStateByEvent(event);
- @Override
- protected void handleInProgressEvent(int actionCode, MotionEvent event) {
- switch (actionCode) {
- case MotionEvent.ACTION_POINTER_UP:
- // Gesture ended but
- updateStateByEvent(event);
-
- if (!mSloppyGesture) {
- mListener.onShoveEnd(this);
- }
-
- resetState();
- break;
-
- case MotionEvent.ACTION_CANCEL:
- if (!mSloppyGesture) {
- mListener.onShoveEnd(this);
- }
-
- resetState();
- break;
-
- case MotionEvent.ACTION_MOVE:
- updateStateByEvent(event);
-
- // Only accept the event if our relative pressure is within
- // a certain limit. This can help filter shaky data as a
- // finger is lifted. Also check that shove is meaningful.
- if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD
- && Math.abs(getShovePixelsDelta()) > 0.5f) {
- final boolean updatePrevious = mListener.onShove(this);
- if (updatePrevious) {
- mPrevEvent.recycle();
- mPrevEvent = MotionEvent.obtain(event);
- }
- }
- break;
+ if (!sloppyGesture) {
+ listener.onShoveEnd(this);
}
- }
-
- @Override
- protected void resetState() {
- super.resetState();
- mSloppyGesture = false;
- mPrevAverageY = 0.0f;
- mCurrAverageY = 0.0f;
- }
- @Override
- protected void updateStateByEvent(MotionEvent curr) {
- super.updateStateByEvent(curr);
+ resetState();
+ break;
- final MotionEvent prev = mPrevEvent;
- float py0 = prev.getY(0);
- float py1 = prev.getY(1);
- mPrevAverageY = (py0 + py1) / 2.0f;
+ case MotionEvent.ACTION_CANCEL:
+ if (!sloppyGesture) {
+ listener.onShoveEnd(this);
+ }
- float cy0 = curr.getY(0);
- float cy1 = curr.getY(1);
- mCurrAverageY = (cy0 + cy1) / 2.0f;
+ resetState();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ updateStateByEvent(event);
+
+ // Only accept the event if our relative pressure is within
+ // a certain limit. This can help filter shaky data as a
+ // finger is lifted. Also check that shove is meaningful.
+ if (currPressure / prevPressure > PRESSURE_THRESHOLD
+ && Math.abs(getShovePixelsDelta()) > 0.5f) {
+ final boolean updatePrevious = listener.onShove(this);
+ if (updatePrevious) {
+ prevEvent.recycle();
+ prevEvent = MotionEvent.obtain(event);
+ }
+ }
+ break;
}
-
- @Override
- protected boolean isSloppyGesture(MotionEvent event) {
- boolean sloppy = super.isSloppyGesture(event);
- if (sloppy)
- return true;
-
- // If it's not traditionally sloppy, we check if the angle between
- // fingers
- // is acceptable.
- double angle = Math.abs(Math.atan2(mCurrFingerDiffY, mCurrFingerDiffX));
- // about 20 degrees, left or right
- return !((0.0f < angle && angle < 0.35f) || 2.79f < angle
- && angle < Math.PI);
+ }
+
+ @Override
+ protected void resetState() {
+ super.resetState();
+ sloppyGesture = false;
+ prevAverageY = 0.0f;
+ currAverageY = 0.0f;
+ }
+
+ @Override
+ protected void updateStateByEvent(MotionEvent curr) {
+ super.updateStateByEvent(curr);
+
+ final MotionEvent prev = prevEvent;
+ float py0 = prev.getY(0);
+ float py1 = prev.getY(1);
+ prevAverageY = (py0 + py1) / 2.0f;
+
+ float cy0 = curr.getY(0);
+ float cy1 = curr.getY(1);
+ currAverageY = (cy0 + cy1) / 2.0f;
+ }
+
+ @Override
+ protected boolean isSloppyGesture(MotionEvent event) {
+ boolean sloppy = super.isSloppyGesture(event);
+ if (sloppy) {
+ return true;
}
- /**
- * Return the distance in pixels from the previous shove event to the
- * current event.
- *
- * @return The current distance in pixels.
- */
- public float getShovePixelsDelta() {
- return mCurrAverageY - mPrevAverageY;
- }
+ // If it's not traditionally sloppy, we check if the angle between
+ // fingers
+ // is acceptable.
+ double angle = Math.abs(Math.atan2(currFingerDiffY, currFingerDiffX));
+ // about 20 degrees, left or right
+ return !((0.0f < angle && angle < 0.35f) || 2.79f < angle
+ && angle < Math.PI);
+ }
+
+ /**
+ * Return the distance in pixels from the previous shove event to the
+ * current event.
+ *
+ * @return The current distance in pixels.
+ */
+ public float getShovePixelsDelta() {
+ return currAverageY - prevAverageY;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/TwoFingerGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/TwoFingerGestureDetector.java
index 6be0b46d5b..71fb9aa168 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/TwoFingerGestureDetector.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/TwoFingerGestureDetector.java
@@ -9,19 +9,19 @@ import android.view.ViewConfiguration;
/**
* @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie
* (code.almeros.com)
- *
+ * <p>
* All rights reserved.
- *
+ * <p>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ * <p>
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ * <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -37,187 +37,189 @@ import android.view.ViewConfiguration;
*/
public abstract class TwoFingerGestureDetector extends BaseGestureDetector {
- private final float mEdgeSlop;
-
- protected float mPrevFingerDiffX;
- protected float mPrevFingerDiffY;
- protected float mCurrFingerDiffX;
- protected float mCurrFingerDiffY;
-
- private float mCurrLen;
- private float mPrevLen;
-
- private PointF mFocus;
-
- public TwoFingerGestureDetector(Context context) {
- super(context);
-
- ViewConfiguration config = ViewConfiguration.get(context);
- mEdgeSlop = config.getScaledEdgeSlop();
+ private final float edgeSlop;
+
+ protected float prevFingerDiffX;
+ protected float prevFingerDiffY;
+ protected float currFingerDiffX;
+ protected float currFingerDiffY;
+
+ private float currLen;
+ private float prevLen;
+
+ private PointF focus;
+
+ public TwoFingerGestureDetector(Context context) {
+ super(context);
+
+ ViewConfiguration config = ViewConfiguration.get(context);
+
+ // We divide edge slop by 2 to make rotation gesture happen more easily #6870
+ edgeSlop = config.getScaledEdgeSlop() / 2;
+ }
+
+ @Override
+ protected abstract void handleStartProgressEvent(int actionCode,
+ MotionEvent event);
+
+ @Override
+ protected abstract void handleInProgressEvent(int actionCode,
+ MotionEvent event);
+
+ protected void updateStateByEvent(MotionEvent curr) {
+ super.updateStateByEvent(curr);
+
+ final MotionEvent prev = prevEvent;
+
+ currLen = -1;
+ prevLen = -1;
+
+ // Previous
+ final float px0 = prev.getX(0);
+ final float py0 = prev.getY(0);
+ final float px1 = prev.getX(1);
+ final float py1 = prev.getY(1);
+ final float pvx = px1 - px0;
+ final float pvy = py1 - py0;
+ prevFingerDiffX = pvx;
+ prevFingerDiffY = pvy;
+
+ // Current
+ final float cx0 = curr.getX(0);
+ final float cy0 = curr.getY(0);
+ final float cx1 = curr.getX(1);
+ final float cy1 = curr.getY(1);
+ final float cvx = cx1 - cx0;
+ final float cvy = cy1 - cy0;
+ currFingerDiffX = cvx;
+ currFingerDiffY = cvy;
+ focus = determineFocalPoint(curr);
+ }
+
+ /**
+ * Return the current distance between the two pointers forming the gesture
+ * in progress.
+ *
+ * @return Distance between pointers in pixels.
+ */
+ public float getCurrentSpan() {
+ if (currLen == -1) {
+ final float cvx = currFingerDiffX;
+ final float cvy = currFingerDiffY;
+ currLen = (float) Math.sqrt(cvx * cvx + cvy * cvy);
}
-
- @Override
- protected abstract void handleStartProgressEvent(int actionCode,
- MotionEvent event);
-
- @Override
- protected abstract void handleInProgressEvent(int actionCode,
- MotionEvent event);
-
- protected void updateStateByEvent(MotionEvent curr) {
- super.updateStateByEvent(curr);
-
- final MotionEvent prev = mPrevEvent;
-
- mCurrLen = -1;
- mPrevLen = -1;
-
- // Previous
- final float px0 = prev.getX(0);
- final float py0 = prev.getY(0);
- final float px1 = prev.getX(1);
- final float py1 = prev.getY(1);
- final float pvx = px1 - px0;
- final float pvy = py1 - py0;
- mPrevFingerDiffX = pvx;
- mPrevFingerDiffY = pvy;
-
- // Current
- final float cx0 = curr.getX(0);
- final float cy0 = curr.getY(0);
- final float cx1 = curr.getX(1);
- final float cy1 = curr.getY(1);
- final float cvx = cx1 - cx0;
- final float cvy = cy1 - cy0;
- mCurrFingerDiffX = cvx;
- mCurrFingerDiffY = cvy;
- mFocus = determineFocalPoint(curr);
+ return currLen;
+ }
+
+ /**
+ * Return the previous distance between the two pointers forming the gesture
+ * in progress.
+ *
+ * @return Previous distance between pointers in pixels.
+ */
+ public float getPreviousSpan() {
+ if (prevLen == -1) {
+ final float pvx = prevFingerDiffX;
+ final float pvy = prevFingerDiffY;
+ prevLen = (float) Math.sqrt(pvx * pvx + pvy * pvy);
}
-
- /**
- * Return the current distance between the two pointers forming the gesture
- * in progress.
- *
- * @return Distance between pointers in pixels.
- */
- public float getCurrentSpan() {
- if (mCurrLen == -1) {
- final float cvx = mCurrFingerDiffX;
- final float cvy = mCurrFingerDiffY;
- mCurrLen = (float) Math.sqrt(cvx * cvx + cvy * cvy);
- }
- return mCurrLen;
+ return prevLen;
+ }
+
+ /**
+ * MotionEvent has no getRawX(int) method; simulate it pending future API
+ * approval.
+ *
+ * @param event Motion Event
+ * @param pointerIndex Pointer Index
+ * @return Raw x value or 0
+ */
+ protected static float getRawX(MotionEvent event, int pointerIndex) {
+ float offset = event.getRawX() - event.getX();
+ if (pointerIndex < event.getPointerCount()) {
+ return event.getX(pointerIndex) + offset;
}
-
- /**
- * Return the previous distance between the two pointers forming the gesture
- * in progress.
- *
- * @return Previous distance between pointers in pixels.
- */
- public float getPreviousSpan() {
- if (mPrevLen == -1) {
- final float pvx = mPrevFingerDiffX;
- final float pvy = mPrevFingerDiffY;
- mPrevLen = (float) Math.sqrt(pvx * pvx + pvy * pvy);
- }
- return mPrevLen;
+ return 0.0f;
+ }
+
+ /**
+ * MotionEvent has no getRawY(int) method; simulate it pending future API
+ * approval.
+ *
+ * @param event Motion Event
+ * @param pointerIndex Pointer Index
+ * @return Raw y value or 0
+ */
+ protected static float getRawY(MotionEvent event, int pointerIndex) {
+ float offset = event.getRawY() - event.getY();
+ if (pointerIndex < event.getPointerCount()) {
+ return event.getY(pointerIndex) + offset;
}
-
- /**
- * MotionEvent has no getRawX(int) method; simulate it pending future API
- * approval.
- *
- * @param event Motion Event
- * @param pointerIndex Pointer Index
- * @return Raw x value or 0
- */
- protected static float getRawX(MotionEvent event, int pointerIndex) {
- float offset = event.getRawX() - event.getX();
- if (pointerIndex < event.getPointerCount()) {
- return event.getX(pointerIndex) + offset;
- }
- return 0.0f;
+ return 0.0f;
+ }
+
+ /**
+ * Check if we have a sloppy gesture. Sloppy gestures can happen if the edge
+ * of the user's hand is touching the screen, for example.
+ *
+ * @param event Motion Event
+ * @return {@code true} if is sloppy gesture, {@code false} if not
+ */
+ protected boolean isSloppyGesture(MotionEvent event) {
+ // As orientation can change, query the metrics in touch down
+ DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+ float rightSlopEdge = metrics.widthPixels - edgeSlop;
+ float bottomSlopEdge = metrics.heightPixels - edgeSlop;
+
+ final float edgeSlop = this.edgeSlop;
+
+ final float x0 = event.getRawX();
+ final float y0 = event.getRawY();
+ final float x1 = getRawX(event, 1);
+ final float y1 = getRawY(event, 1);
+
+ boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x0 > rightSlopEdge
+ || y0 > bottomSlopEdge;
+ boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop || x1 > rightSlopEdge
+ || y1 > bottomSlopEdge;
+
+ if (p0sloppy && p1sloppy) {
+ return true;
+ } else if (p0sloppy) {
+ return true;
+ } else if (p1sloppy) {
+ return true;
}
-
- /**
- * MotionEvent has no getRawY(int) method; simulate it pending future API
- * approval.
- *
- * @param event Motion Event
- * @param pointerIndex Pointer Index
- * @return Raw y value or 0
- */
- protected static float getRawY(MotionEvent event, int pointerIndex) {
- float offset = event.getRawY() - event.getY();
- if (pointerIndex < event.getPointerCount()) {
- return event.getY(pointerIndex) + offset;
- }
- return 0.0f;
+ return false;
+ }
+
+ /**
+ * Determine (multi)finger focal point (a.k.a. center point between all
+ * fingers)
+ *
+ * @param motionEvent Motion Event
+ * @return PointF focal point
+ */
+ public static PointF determineFocalPoint(MotionEvent motionEvent) {
+ // Number of fingers on screen
+ final int pCount = motionEvent.getPointerCount();
+ float x = 0.0f;
+ float y = 0.0f;
+
+ for (int i = 0; i < pCount; i++) {
+ x += motionEvent.getX(i);
+ y += motionEvent.getY(i);
}
- /**
- * Check if we have a sloppy gesture. Sloppy gestures can happen if the edge
- * of the user's hand is touching the screen, for example.
- *
- * @param event Motion Event
- * @return {@code true} if is sloppy gesture, {@code false} if not
- */
- protected boolean isSloppyGesture(MotionEvent event) {
- // As orientation can change, query the metrics in touch down
- DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
- float mRightSlopEdge = metrics.widthPixels - mEdgeSlop;
- float mBottomSlopEdge = metrics.heightPixels - mEdgeSlop;
-
- final float edgeSlop = mEdgeSlop;
-
- final float x0 = event.getRawX();
- final float y0 = event.getRawY();
- final float x1 = getRawX(event, 1);
- final float y1 = getRawY(event, 1);
-
- boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x0 > mRightSlopEdge
- || y0 > mBottomSlopEdge;
- boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop || x1 > mRightSlopEdge
- || y1 > mBottomSlopEdge;
-
- if (p0sloppy && p1sloppy) {
- return true;
- } else if (p0sloppy) {
- return true;
- } else if (p1sloppy) {
- return true;
- }
- return false;
- }
+ return new PointF(x / pCount, y / pCount);
+ }
- /**
- * Determine (multi)finger focal point (a.k.a. center point between all
- * fingers)
- *
- * @param e Motion Event
- * @return PointF focal point
- */
- public static PointF determineFocalPoint(MotionEvent e) {
- // Number of fingers on screen
- final int pCount = e.getPointerCount();
- float x = 0.0f;
- float y = 0.0f;
-
- for (int i = 0; i < pCount; i++) {
- x += e.getX(i);
- y += e.getY(i);
- }
-
- return new PointF(x / pCount, y / pCount);
- }
+ public float getFocusX() {
+ return focus.x;
+ }
- public float getFocusX() {
- return mFocus.x;
- }
-
- public float getFocusY() {
- return mFocus.y;
- }
+ public float getFocusY() {
+ return focus.y;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java
new file mode 100644
index 0000000000..9d20e968c8
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java
@@ -0,0 +1,104 @@
+package com.mapbox.mapboxsdk;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
+
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException;
+import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
+import com.mapbox.mapboxsdk.telemetry.MapboxEventManager;
+
+public final class Mapbox {
+
+ private static Mapbox INSTANCE;
+ private Context context;
+ private String accessToken;
+ private Boolean connected;
+
+ /**
+ * Get an instance of Mapbox.
+ * <p>
+ * This class manages the active access token, application context and connectivity state.
+ * </p>
+ *
+ * @param context Android context which holds or is an application context
+ * @param accessToken Mapbox access token
+ * @return the single instance of Mapbox
+ */
+ public static synchronized Mapbox getInstance(@NonNull Context context, @NonNull String accessToken) {
+ if (INSTANCE == null) {
+ Context appContext = context.getApplicationContext();
+ INSTANCE = new Mapbox(appContext, accessToken);
+ MapboxEventManager.getMapboxEventManager().initialize(appContext, accessToken);
+ ConnectivityReceiver.instance(appContext);
+ }
+ return INSTANCE;
+ }
+
+ private Mapbox(@NonNull Context context, @NonNull String accessToken) {
+ this.context = context;
+ this.accessToken = accessToken;
+ }
+
+ /**
+ * Access Token for this application.
+ *
+ * @return Mapbox Access Token
+ */
+ public static String getAccessToken() {
+ validateAccessToken();
+ return INSTANCE.accessToken;
+ }
+
+ /**
+ * Runtime validation of Access Token.
+ *
+ * @throws InvalidAccessTokenException exception thrown when not using a valid accessToken
+ */
+ private static void validateAccessToken() throws InvalidAccessTokenException {
+ String accessToken = INSTANCE.accessToken;
+ if (TextUtils.isEmpty(accessToken) || (!accessToken.toLowerCase(MapboxConstants.MAPBOX_LOCALE).startsWith("pk.")
+ && !accessToken.toLowerCase(MapboxConstants.MAPBOX_LOCALE).startsWith("sk."))) {
+ throw new InvalidAccessTokenException();
+ }
+ }
+
+ /**
+ * Application context
+ */
+ public static Context getApplicationContext() {
+ return INSTANCE.context;
+ }
+
+ /**
+ * Manually sets the connectivity state of the app. This is useful for apps that control their
+ * own connectivity state and want to bypass any checks to the ConnectivityManager.
+ *
+ * @param connected flag to determine the connectivity state, true for connected, false for
+ * disconnected, null for ConnectivityManager to determine.
+ */
+ public static synchronized void setConnected(Boolean connected) {
+ // Connectivity state overridden by app
+ INSTANCE.connected = connected;
+ }
+
+ /**
+ * Determines whether we have an Internet connection available. Please do not rely on this
+ * method in your apps, this method is used internally by the SDK.
+ *
+ * @return true if there is an Internet connection, false otherwise
+ */
+ public static synchronized Boolean isConnected() {
+ if (INSTANCE.connected != null) {
+ // Connectivity state overridden by app
+ return INSTANCE.connected;
+ }
+
+ ConnectivityManager cm = (ConnectivityManager) INSTANCE.context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
+ return (activeNetwork != null && activeNetwork.isConnected());
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapboxAccountManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapboxAccountManager.java
deleted file mode 100644
index b33d01a105..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapboxAccountManager.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package com.mapbox.mapboxsdk;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.text.TextUtils;
-
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
-import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException;
-import com.mapbox.mapboxsdk.exceptions.MapboxAccountManagerNotStartedException;
-import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
-import com.mapbox.mapboxsdk.telemetry.MapboxEventManager;
-
-public class MapboxAccountManager {
-
- private static MapboxAccountManager mapboxAccountManager = null;
-
- private final String accessToken;
- private final Context applicationContext;
-
- private Boolean connected = null;
-
- /**
- * MapboxAccountManager should NOT be instantiated directly.
- * Use @see MapboxAccountManager#getInstance() instead.
- *
- * @param applicationContext Context used to get ApplicationContext
- * @param accessToken Mapbox Access Token
- */
- private MapboxAccountManager(Context applicationContext, String accessToken) {
- super();
- this.applicationContext = applicationContext.getApplicationContext();
- this.accessToken = accessToken;
- }
-
- /**
- * Primary entry point to Mapbox for implementing developers.
- * Must be configured in either Application.onCreate() or Launch Activity.onCreate()
- *
- * @param context Context used to get Application Context
- * @param accessToken Mapbox Access Token. You can get one on the Mapbox Web site.
- * @return MapboxAccountManager instance for app
- */
- public static MapboxAccountManager start(Context context, String accessToken) {
- if (mapboxAccountManager == null) {
- //Create a new account manager
- mapboxAccountManager = new MapboxAccountManager(context, accessToken);
-
- //Initialize the event manager
- MapboxEventManager.getMapboxEventManager().initialize(context, accessToken);
-
- //Register a receiver to listen for connectivity updates
- ConnectivityReceiver.instance(context);
- }
-
- return mapboxAccountManager;
- }
-
- /**
- * Internal Use Only
- * Get an instance of MapboxAccountManager configured with the app's Access Token
- *
- * @return MapboxAccountManager instance for app. May be NULL if not configured yet.
- */
- public static MapboxAccountManager getInstance() {
- if (mapboxAccountManager == null) {
- throw new MapboxAccountManagerNotStartedException();
- }
-
- return mapboxAccountManager;
- }
-
- /**
- * Access Token for this application.
- *
- * @return Mapbox Access Token
- */
- public String getAccessToken() {
- return accessToken;
- }
-
- /**
- * Runtime validation of Access Token.
- *
- * @param accessToken Access Token to check
- * @throws InvalidAccessTokenException the exception thrown
- */
- public static void validateAccessToken(String accessToken) throws InvalidAccessTokenException {
- if (TextUtils.isEmpty(accessToken) || (!accessToken.toLowerCase(MapboxConstants.MAPBOX_LOCALE).startsWith("pk.") && !accessToken.toLowerCase(MapboxConstants.MAPBOX_LOCALE).startsWith("sk."))) {
- throw new InvalidAccessTokenException();
- }
- }
-
- /**
- * Manually sets the connectivity state of the app. This is useful for apps that control their
- * own connectivity state and want to bypass any checks to the ConnectivityManager.
- *
- * @param connected flag to determine the connectivity state, true for connected, false for
- * disconnected, null for ConnectivityManager to determine.
- */
- public void setConnected(Boolean connected) {
- // Connectivity state overridden by app
- this.connected = connected;
- }
-
- /**
- * Determines whether we have an Internet connection available. Please do not rely on this
- * method in your apps, this method is used internally by the SDK.
- *
- * @return true if there is an Internet connection, false otherwise
- */
- public Boolean isConnected() {
- if (connected != null) {
- // Connectivity state overridden by app
- return connected;
- }
-
- ConnectivityManager cm = (ConnectivityManager) applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
- return (activeNetwork != null && activeNetwork.isConnected());
- }
-
- /**
- * Not public API
- * @return the Application Context
- */
- public Context getApplicationContext() {
- return applicationContext;
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java
index d7df692e17..831c1db5a3 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java
@@ -15,104 +15,127 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
*/
public abstract class Annotation implements Comparable<Annotation> {
- /**
- * <p>
- * The annotation id
- * </p>
- * Internal C++ id is stored as unsigned int.
- */
- private long id = -1; // -1 unless added to a MapView
- protected MapboxMap mapboxMap;
- protected MapView mapView;
+ /**
+ * <p>
+ * The annotation id
+ * </p>
+ * Internal C++ id is stored as unsigned int.
+ */
+ private long id = -1; // -1 unless added to a MapView
+ protected MapboxMap mapboxMap;
+ protected MapView mapView;
- protected Annotation() {
- }
+ protected Annotation() {
+ }
- /**
- * <p>
- * Gets the annotation's unique ID.
- * </p>
- * This ID is unique for a MapView instance and is suitable for associating your own extra
- * data with.
- *
- * @return the assigned id
- */
- public long getId() {
- return id;
- }
+ /**
+ * <p>
+ * Gets the annotation's unique ID.
+ * </p>
+ * This ID is unique for a MapView instance and is suitable for associating your own extra
+ * data with.
+ *
+ * @return the assigned id.
+ */
+ public long getId() {
+ return id;
+ }
- public void remove() {
- if (mapboxMap == null) {
- return;
- }
- mapboxMap.removeAnnotation(this);
+ /**
+ * Do not use this method, used internally by the SDK.
+ */
+ public void remove() {
+ if (mapboxMap == null) {
+ return;
}
+ mapboxMap.removeAnnotation(this);
+ }
- /**
- * Do not use this method. Used internally by the SDK.
- *
- * @param id the assigned id
- */
- public void setId(long id) {
- this.id = id;
- }
+ /**
+ * Do not use this method, used internally by the SDK.
+ *
+ * @param id the assigned id
+ */
+ public void setId(long id) {
+ this.id = id;
+ }
- /**
- * Do not use this method. Used internally by the SDK.
- *
- * @param mapboxMap the hosting mapbox map
- */
- public void setMapboxMap(MapboxMap mapboxMap) {
- this.mapboxMap = mapboxMap;
- }
+ /**
+ * Do not use this method, used internally by the SDK.
+ *
+ * @param mapboxMap the hosting mapbox map
+ */
+ public void setMapboxMap(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ }
- /**
- * Gets the hosting mapbox map.
- *
- * @return the MapboxMap
- */
- protected MapboxMap getMapboxMap() {
- return mapboxMap;
- }
+ /**
+ * Gets the hosting mapbox map.
+ *
+ * @return the MapboxMap
+ */
+ protected MapboxMap getMapboxMap() {
+ return mapboxMap;
+ }
- /**
- * Don not use this method. Used internally by the SDK.
- *
- * @param mapView the hosting map view
- */
- public void setMapView(MapView mapView) {
- this.mapView = mapView;
- }
+ /**
+ * Do not use this method, used internally by the SDK.
+ *
+ * @param mapView the hosting map view
+ */
+ public void setMapView(MapView mapView) {
+ this.mapView = mapView;
+ }
- /**
- * Gets the hosting map view.
- *
- * @return The MapView
- */
- protected MapView getMapView() {
- return mapView;
- }
+ /**
+ * Gets the hosting map view.
+ *
+ * @return The MapView
+ */
+ protected MapView getMapView() {
+ return mapView;
+ }
- @Override
- public int compareTo(@NonNull Annotation annotation) {
- if (id < annotation.getId()) {
- return 1;
- } else if (id > annotation.getId()) {
- return -1;
- }
- return 0;
+ @Override
+ public int compareTo(@NonNull Annotation annotation) {
+ if (id < annotation.getId()) {
+ return 1;
+ } else if (id > annotation.getId()) {
+ return -1;
}
+ return 0;
+ }
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || !(o instanceof Annotation)) return false;
- Annotation that = (Annotation) o;
- return id == that.getId();
+ /**
+ * Compares this {@link PolylineOptions} object with another {@link PolylineOptions} and
+ * determines if their color, alpha, width, and vertices match.
+ *
+ * @param object Another {@link PolylineOptions} to compare with this object.
+ * @return True if color, alpha, width, and vertices match this {@link PolylineOptions} object.
+ * Else, false.
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
}
-
- @Override
- public int hashCode() {
- return (int) (getId() ^ (getId() >>> 32));
+ if (object == null || !(object instanceof Annotation)) {
+ return false;
}
+ Annotation that = (Annotation) object;
+ return id == that.getId();
+ }
+
+ /**
+ * Gives an integer which can be used as the bucket number for storing elements of the set/map.
+ * This bucket number is the address of the element inside the set/map. There's no guarantee
+ * that this hash value will be consistent between different Java implementations, or even
+ * between different execution runs of the same program.
+ *
+ * @return integer value you can use for storing element.
+ */
+ @Override
+ public int hashCode() {
+ return (int) (getId() ^ (getId() >>> 32));
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java
index 3adeb52ea7..82868e2888 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java
@@ -6,7 +6,7 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
/**
* Abstract builder class for composing custom Marker objects.
- *
+ * <p>
* Extending this class requires implementing Parceable interface.
*
* @param <U> Type of the marker to be composed
@@ -14,49 +14,107 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
*/
public abstract class BaseMarkerOptions<U extends Marker, T extends BaseMarkerOptions<U, T>> implements Parcelable {
- protected LatLng position;
- protected String snippet;
- protected String title;
- protected Icon icon;
+ protected LatLng position;
+ protected String snippet;
+ protected String title;
+ protected Icon icon;
- public T position(LatLng position) {
- this.position = position;
- return getThis();
- }
+ /**
+ * Set the geographical location of the Marker.
+ *
+ * @param position the location to position the {@link Marker}.
+ * @return the object for which the method was called.
+ */
+ public T position(LatLng position) {
+ this.position = position;
+ return getThis();
+ }
- public T snippet(String snippet) {
- this.snippet = snippet;
- return getThis();
- }
+ /**
+ * Set the snippet of the Marker.
+ *
+ * @param snippet the snippet of the {@link Marker}.
+ * @return the object for which the method was called.
+ */
+ public T snippet(String snippet) {
+ this.snippet = snippet;
+ return getThis();
+ }
- public T title(String title) {
- this.title = title;
- return getThis();
- }
+ /**
+ * Set the title of the Marker.
+ *
+ * @param title the title of the {@link Marker}.
+ * @return the object for which the method was called.
+ */
+ public T title(String title) {
+ this.title = title;
+ return getThis();
+ }
- public T icon(Icon icon) {
- this.icon = icon;
- return getThis();
- }
+ /**
+ * Set the icon of the Marker.
+ *
+ * @param icon the icon of the {@link Marker}.
+ * @return the object for which the method was called.
+ */
+ public T icon(Icon icon) {
+ this.icon = icon;
+ return getThis();
+ }
- public T setIcon(Icon icon) {
- return icon(icon);
- }
+ /**
+ * Set the icon of the Marker.
+ *
+ * @param icon the icon of the {@link Marker}.
+ * @return the object for which the method was called.
+ */
+ public T setIcon(Icon icon) {
+ return icon(icon);
+ }
- public T setPosition(LatLng position) {
- return position(position);
- }
+ /**
+ * Set the geographical location of the Marker.
+ *
+ * @param position the location to position the {@link Marker}.
+ * @return the object for which the method was called.
+ */
+ public T setPosition(LatLng position) {
+ return position(position);
+ }
- public T setSnippet(String snippet) {
- return snippet(snippet);
- }
+ /**
+ * Set the snippet of the Marker.
+ *
+ * @param snippet the snippet of the {@link Marker}.
+ * @return the object for which the method was called.
+ */
+ public T setSnippet(String snippet) {
+ return snippet(snippet);
+ }
- public T setTitle(String title) {
- return title(title);
- }
+ /**
+ * Set the title of the Marker.
+ *
+ * @param title the title of the {@link Marker}.
+ * @return the object for which the method was called.
+ */
+ public T setTitle(String title) {
+ return title(title);
+ }
- public abstract T getThis();
+ /**
+ * Get the instance of the object for which this method was called.
+ *
+ * @return the object for which the this method was called.
+ */
+ public abstract T getThis();
- public abstract U getMarker();
+ /**
+ * Get the Marker.
+ *
+ * @return the Marker created from this builder.
+ */
+ public abstract U getMarker();
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java
index d4eb390ab2..ddedf3debf 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java
@@ -12,270 +12,271 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
* Extending this class requires implementing Parceable interface.
* </p>
*
- * @param <U> Type of the marker view to be composed
- * @param <T> Type of the builder to be used for composing
+ * @param <U> Type of the marker view to be composed.
+ * @param <T> Type of the builder to be used for composing.
*/
-public abstract class BaseMarkerViewOptions<U extends MarkerView, T extends BaseMarkerViewOptions<U, T>> implements Parcelable {
+public abstract class BaseMarkerViewOptions<U extends MarkerView, T extends BaseMarkerViewOptions<U, T>>
+ implements Parcelable {
- protected LatLng position;
- protected String snippet;
- protected String title;
- protected Icon icon;
- protected boolean flat;
- protected float anchorU = 0.5f;
- protected float anchorV = 1f;
- protected float infoWindowAnchorU = 0.5f;
- protected float infoWindowAnchorV = 0.0f;
- protected float rotation;
- protected boolean visible = true;
- protected boolean selected;
- protected float alpha = 1.0f;
+ protected LatLng position;
+ protected String snippet;
+ protected String title;
+ protected Icon icon;
+ protected boolean flat;
+ protected float anchorU = 0.5f;
+ protected float anchorV = 1f;
+ protected float infoWindowAnchorU = 0.5f;
+ protected float infoWindowAnchorV = 0.0f;
+ protected float rotation;
+ protected boolean visible = true;
+ protected boolean selected;
+ protected float alpha = 1.0f;
- /**
- * Default constructor
- */
- public BaseMarkerViewOptions() {
- }
+ /**
+ * Default constructor
+ */
+ public BaseMarkerViewOptions() {
+ }
- /**
- * Set the geographical location of the MarkerView.
- *
- * @param position the location to position the MarkerView
- * @return the object for which the method was called
- */
- public T position(@NonNull LatLng position) {
- this.position = position;
- return getThis();
- }
+ /**
+ * Set the geographical location of the MarkerView.
+ *
+ * @param position the location to position the {@link MarkerView}.
+ * @return the object for which the method was called.
+ */
+ public T position(@NonNull LatLng position) {
+ this.position = position;
+ return getThis();
+ }
- /**
- * Set the snippet of the MarkerView.
- *
- * @param snippet the snippet of the MarkerView
- * @return the object for which the method was called
- */
- public T snippet(String snippet) {
- this.snippet = snippet;
- return getThis();
- }
+ /**
+ * Set the snippet of the MarkerView.
+ *
+ * @param snippet the snippet of the {@link MarkerView}.
+ * @return the object for which the method was called.
+ */
+ public T snippet(String snippet) {
+ this.snippet = snippet;
+ return getThis();
+ }
- /**
- * Set the title of the MarkerView.
- *
- * @param title the title of the MarkerView
- * @return the object for which the method was called
- */
- public T title(String title) {
- this.title = title;
- return getThis();
- }
+ /**
+ * Set the title of the MarkerView.
+ *
+ * @param title the title of the {@link MarkerView}.
+ * @return the object for which the method was called.
+ */
+ public T title(String title) {
+ this.title = title;
+ return getThis();
+ }
- /**
- * Set the icon of the MarkerView.
- *
- * @param icon the icon of the MarkerView
- * @return the object for which the method was called
- */
- public T icon(Icon icon) {
- this.icon = icon;
- return getThis();
- }
+ /**
+ * Set the icon of the MarkerView.
+ *
+ * @param icon the icon of the {@link MarkerView}.
+ * @return the object for which the method was called.
+ */
+ public T icon(Icon icon) {
+ this.icon = icon;
+ return getThis();
+ }
- /**
- * Set the flat state of the MarkerView.
- *
- * @param flat the flat state of the MarkerView
- * @return the object for which the method was called
- */
- public T flat(boolean flat) {
- this.flat = flat;
- return getThis();
- }
+ /**
+ * Set the flat state of the MarkerView.
+ *
+ * @param flat the flat state of the {@link MarkerView}.
+ * @return the object for which the method was called.
+ */
+ public T flat(boolean flat) {
+ this.flat = flat;
+ return getThis();
+ }
- /**
- * Set the anchor of the MarkerView.
- *
- * @param u the u-value
- * @param v the v-value
- * @return the object for which the method was called
- */
- public T anchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
- this.anchorU = u;
- this.anchorV = v;
- return getThis();
- }
+ /**
+ * Set the anchor of the {@link MarkerView}.
+ *
+ * @param u the u-value.
+ * @param v the v-value.
+ * @return the object for which the method was called.
+ */
+ public T anchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
+ this.anchorU = u;
+ this.anchorV = v;
+ return getThis();
+ }
- /**
- * Set the InfoWindow anchor of the MarkerView.
- *
- * @param u the u-value
- * @param v the v-values
- * @return the object for which the method was called
- */
- public T infoWindowAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
- this.infoWindowAnchorU = u;
- this.infoWindowAnchorV = v;
- return getThis();
- }
+ /**
+ * Set the InfoWindow anchor of the {@link MarkerView}.
+ *
+ * @param u the u-value.
+ * @param v the v-values.
+ * @return the object for which the method was called.
+ */
+ public T infoWindowAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
+ this.infoWindowAnchorU = u;
+ this.infoWindowAnchorV = v;
+ return getThis();
+ }
- /**
- * Set the rotation of the MarkerView.
- *
- * @param rotation the rotation value
- * @return the object for which the method was called
- */
- public T rotation(float rotation) {
- this.rotation = rotation;
- while (this.rotation > 360) {
- this.rotation -= 360;
- }
- while (this.rotation < 0) {
- this.rotation += 360;
- }
- return getThis();
+ /**
+ * Set the rotation of the {@link MarkerView}.
+ *
+ * @param rotation the rotation value.
+ * @return the object for which the method was called.
+ */
+ public T rotation(float rotation) {
+ this.rotation = rotation;
+ while (this.rotation > 360) {
+ this.rotation -= 360;
}
-
- /**
- * Set the visibility state of the MarkerView.
- *
- * @param visible the visible state
- * @return the object for which the method was called
- */
- public T visible(boolean visible) {
- this.visible = visible;
- return getThis();
+ while (this.rotation < 0) {
+ this.rotation += 360;
}
+ return getThis();
+ }
- /**
- * Set the alpha of the MarkerView.
- *
- * @param alpha the alpha value
- * @return the object for which the method was called
- */
- public T alpha(float alpha) {
- this.alpha = alpha;
- return getThis();
- }
+ /**
+ * Set the visibility state of the {@link MarkerView}.
+ *
+ * @param visible the visible state.
+ * @return the object for which the method was called.
+ */
+ public T visible(boolean visible) {
+ this.visible = visible;
+ return getThis();
+ }
- /**
- * Get the geographical location of the MarkerView.
- *
- * @return the geographical location
- */
- public LatLng getPosition() {
- return position;
- }
+ /**
+ * Set the alpha of the {@link MarkerView}.
+ *
+ * @param alpha the alpha value.
+ * @return the object for which the method was called.
+ */
+ public T alpha(float alpha) {
+ this.alpha = alpha;
+ return getThis();
+ }
- /**
- * Get the snippet of the MarkerView.
- *
- * @return the snippet
- */
- public String getSnippet() {
- return snippet;
- }
+ /**
+ * Get the geographical location of the {@link MarkerView}.
+ *
+ * @return the geographical location.
+ */
+ public LatLng getPosition() {
+ return position;
+ }
- /**
- * Get the title of the MarkerView.
- *
- * @return the title
- */
- public String getTitle() {
- return title;
- }
+ /**
+ * Get the snippet of the {@link MarkerView}.
+ *
+ * @return the snippet.
+ */
+ public String getSnippet() {
+ return snippet;
+ }
- /**
- * Get the icon of the MarkerView.
- *
- * @return the icon
- */
- public Icon getIcon() {
- return icon;
- }
+ /**
+ * Get the title of the {@link MarkerView}.
+ *
+ * @return the title.
+ */
+ public String getTitle() {
+ return title;
+ }
- /**
- * Get the flat state of the MarkerView.
- *
- * @return the flat state
- */
- public boolean isFlat() {
- return flat;
- }
+ /**
+ * Get the icon of the {@link MarkerView}.
+ *
+ * @return the icon.
+ */
+ public Icon getIcon() {
+ return icon;
+ }
- /**
- * Get the u-value of the MarkerView anchor.
- *
- * @return the u-value
- */
- public float getAnchorU() {
- return anchorU;
- }
+ /**
+ * Get the flat state of the {@link MarkerView}.
+ *
+ * @return the flat state.
+ */
+ public boolean isFlat() {
+ return flat;
+ }
- /**
- * Get the v-value of the MarkerView anchor.
- *
- * @return the v-value
- */
- public float getAnchorV() {
- return anchorV;
- }
+ /**
+ * Get the u-value of the {@link MarkerView} anchor.
+ *
+ * @return the u-value.
+ */
+ public float getAnchorU() {
+ return anchorU;
+ }
- /**
- * Get the u-value of the MarkerView InfoWindow anchor.
- *
- * @return the u-value
- */
- public float getInfoWindowAnchorU() {
- return infoWindowAnchorU;
- }
+ /**
+ * Get the v-value of the {@link MarkerView} anchor.
+ *
+ * @return the v-value.
+ */
+ public float getAnchorV() {
+ return anchorV;
+ }
- /**
- * Get the v-value of the MarkerView InfoWindow anchor.
- *
- * @return the v-value
- */
- public float getInfoWindowAnchorV() {
- return infoWindowAnchorV;
- }
+ /**
+ * Get the u-value of the MarkerView InfoWindow anchor.
+ *
+ * @return the u-value.
+ */
+ public float getInfoWindowAnchorU() {
+ return infoWindowAnchorU;
+ }
- /**
- * Get the rotation of the MarkerView.
- *
- * @return the rotation value
- */
- public float getRotation() {
- return rotation;
- }
+ /**
+ * Get the v-value of the MarkerView InfoWindow anchor.
+ *
+ * @return the v-value.
+ */
+ public float getInfoWindowAnchorV() {
+ return infoWindowAnchorV;
+ }
- /**
- * Get the visibility state of the MarkerView.
- *
- * @return the visibility state
- */
- public boolean isVisible() {
- return visible;
- }
+ /**
+ * Get the rotation of the MarkerView.
+ *
+ * @return the rotation value.
+ */
+ public float getRotation() {
+ return rotation;
+ }
- /**
- * Get the alpha of the MarkerView.
- *
- * @return the alpha value
- */
- public float getAlpha() {
- return alpha;
- }
+ /**
+ * Get the visibility state of the MarkerView.
+ *
+ * @return the visibility state.
+ */
+ public boolean isVisible() {
+ return visible;
+ }
+
+ /**
+ * Get the alpha of the MarkerView.
+ *
+ * @return the alpha value.
+ */
+ public float getAlpha() {
+ return alpha;
+ }
- /**
- * Get the instance of the object for which this method was called.
- *
- * @return the object for which the this method was called
- */
- public abstract T getThis();
+ /**
+ * Get the instance of the object for which this method was called.
+ *
+ * @return the object for which the this method was called.
+ */
+ public abstract T getThis();
- /**
- * Get the MarkerView.
- *
- * @return the MarkerView created from this builder
- */
- public abstract U getMarker();
+ /**
+ * Get the MarkerView.
+ *
+ * @return the MarkerView created from this builder.
+ */
+ public abstract U getMarker();
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java
index fceeb52713..b1a05ec436 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java
@@ -10,43 +10,73 @@ import com.mapbox.mapboxsdk.maps.MapView;
* @see Marker
*/
public class Icon {
- private Bitmap mBitmap;
- private String mId;
+ private Bitmap mBitmap;
+ private String mId;
- Icon(String id, Bitmap bitmap) {
- mId = id;
- mBitmap = bitmap;
- }
-
- public String getId() {
- return mId;
- }
+ Icon(String id, Bitmap bitmap) {
+ mId = id;
+ mBitmap = bitmap;
+ }
- public Bitmap getBitmap() {
- return mBitmap;
- }
+ /**
+ * {@link String} identifier for this {@link Icon}.
+ *
+ * @return {@link String} identifier for this {@link Icon}.
+ */
+ public String getId() {
+ return mId;
+ }
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ /**
+ * Get the {@link Bitmap} being used for this {@link Icon}.
+ *
+ * @return The {@link Bitmap} being used for the {@link Icon}.
+ */
+ public Bitmap getBitmap() {
+ return mBitmap;
+ }
- Icon icon = (Icon) o;
+ /**
+ * Compares this {@link Icon} object with another {@link Icon} and determines if they match.
+ *
+ * @param object Another {@link Icon} to compare with this object.
+ * @return True if the {@link Icon} being passed in matches this {@link Icon} object. Else,
+ * false.
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object == null || getClass() != object.getClass()) {
+ return false;
+ }
- if (!mBitmap.equals(icon.mBitmap)) return false;
- return mId.equals(icon.mId);
+ Icon icon = (Icon) object;
+ if (!mBitmap.equals(icon.mBitmap)) {
+ return false;
}
+ return mId.equals(icon.mId);
+ }
- @Override
- public int hashCode() {
- int result = 0;
- if (mBitmap != null) {
- result = mBitmap.hashCode();
- }
- if (mId != null) {
- result = 31 * result + mId.hashCode();
- }
- return result;
+ /**
+ * Gives an integer which can be used as the bucket number for storing elements of the set/map.
+ * This bucket number is the address of the element inside the set/map. There's no guarantee
+ * that this hash value will be consistent between different Java implementations, or even
+ * between different execution runs of the same program.
+ *
+ * @return integer value you can use for storing element.
+ */
+ @Override
+ public int hashCode() {
+ int result = 0;
+ if (mBitmap != null) {
+ result = mBitmap.hashCode();
+ }
+ if (mId != null) {
+ result = 31 * result + mId.hashCode();
}
+ return result;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/IconFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/IconFactory.java
index 56c1b643a1..052d5592e4 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/IconFactory.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/IconFactory.java
@@ -29,140 +29,207 @@ import java.io.InputStream;
*/
public final class IconFactory {
- private static final String ICON_ID_PREFIX = "com.mapbox.icons.icon_";
- public static final Bitmap ICON_MARKERVIEW_BITMAP = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
- public static final String ICON_MARKERVIEW_ID = ICON_ID_PREFIX + "marker_view";
-
- private Context mContext;
- private static IconFactory sInstance;
- private Icon mDefaultMarker;
- private Icon mDefaultMarkerView;
- private BitmapFactory.Options mOptions;
-
- private int mNextId = 0;
-
- public static synchronized IconFactory getInstance(@NonNull Context context) {
- if (sInstance == null) {
- sInstance = new IconFactory(context.getApplicationContext());
- }
- return sInstance;
- }
+ private static final String ICON_ID_PREFIX = "com.mapbox.icons.icon_";
+ public static final Bitmap ICON_MARKERVIEW_BITMAP = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
+ public static final String ICON_MARKERVIEW_ID = ICON_ID_PREFIX + "marker_view";
- private IconFactory(@NonNull Context context) {
- mContext = context;
- DisplayMetrics realMetrics = null;
- DisplayMetrics metrics = new DisplayMetrics();
- WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- realMetrics = new DisplayMetrics();
- wm.getDefaultDisplay().getRealMetrics(realMetrics);
- }
- wm.getDefaultDisplay().getMetrics(metrics);
-
- mOptions = new BitmapFactory.Options();
- mOptions.inScaled = true;
- mOptions.inDensity = DisplayMetrics.DENSITY_DEFAULT;
- mOptions.inTargetDensity = metrics.densityDpi;
- if (realMetrics != null) {
- mOptions.inScreenDensity = realMetrics.densityDpi;
- }
- }
+ private Context mContext;
+ private static IconFactory sInstance;
+ private Icon mDefaultMarker;
+ private Icon mDefaultMarkerView;
+ private BitmapFactory.Options mOptions;
- public Icon fromBitmap(@NonNull Bitmap bitmap) {
- if (mNextId < 0) {
- throw new TooManyIconsException();
- }
- String id = ICON_ID_PREFIX + ++mNextId;
- return new Icon(id, bitmap);
- }
+ private int mNextId = 0;
- public Icon fromDrawable(@NonNull Drawable drawable) {
- int width = drawable.getIntrinsicWidth();
- int height = drawable.getIntrinsicHeight();
- return fromDrawable(drawable, width, height);
+ public static synchronized IconFactory getInstance(@NonNull Context context) {
+ if (sInstance == null) {
+ sInstance = new IconFactory(context.getApplicationContext());
}
-
- public Icon fromDrawable(@NonNull Drawable drawable, int width, int height) {
- if ((width < 0) || (height < 0)) {
- return null;
- }
-
- Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- Rect temp = drawable.getBounds();
- Rect bounds = new Rect(0, 0, width, height);
- drawable.setBounds(bounds);
- drawable.draw(canvas);
- drawable.setBounds(temp);
- return fromBitmap(bitmap);
+ return sInstance;
+ }
+
+ private IconFactory(@NonNull Context context) {
+ mContext = context;
+ DisplayMetrics realMetrics = null;
+ DisplayMetrics metrics = new DisplayMetrics();
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ realMetrics = new DisplayMetrics();
+ wm.getDefaultDisplay().getRealMetrics(realMetrics);
}
-
- public Icon fromResource(@DrawableRes int resourceId) {
- Drawable drawable = ContextCompat.getDrawable(mContext, resourceId);
- Bitmap bitmap;
- if (drawable instanceof BitmapDrawable) {
- BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
- bitmap = bitmapDrawable.getBitmap();
- } else {
- if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
- bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
- } else {
- bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
- }
-
- Canvas canvas = new Canvas(bitmap);
- drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
- drawable.draw(canvas);
- }
- return fromBitmap(bitmap);
+ wm.getDefaultDisplay().getMetrics(metrics);
+
+ mOptions = new BitmapFactory.Options();
+ mOptions.inScaled = true;
+ mOptions.inDensity = DisplayMetrics.DENSITY_DEFAULT;
+ mOptions.inTargetDensity = metrics.densityDpi;
+ if (realMetrics != null) {
+ mOptions.inScreenDensity = realMetrics.densityDpi;
}
-
- public Icon defaultMarker() {
- if (mDefaultMarker == null) {
- mDefaultMarker = fromResource(R.drawable.default_marker);
- }
- return mDefaultMarker;
+ }
+
+ /**
+ * Creates an {@link Icon} from a given Bitmap image.
+ *
+ * @param bitmap image used for creating the Icon.
+ * @return The {@link Icon} using the given Bitmap image.
+ */
+ public Icon fromBitmap(@NonNull Bitmap bitmap) {
+ if (mNextId < 0) {
+ throw new TooManyIconsException();
}
-
- public Icon defaultMarkerView() {
- if (mDefaultMarkerView == null) {
- mDefaultMarkerView = fromResource(R.drawable.default_markerview);
- }
- return mDefaultMarkerView;
+ String id = ICON_ID_PREFIX + ++mNextId;
+ return new Icon(id, bitmap);
+ }
+
+ /**
+ * Create an {@link Icon} from a given {@link Drawable}.
+ *
+ * @param drawable A {@link Drawable} object used for creating the {@link Icon}.
+ * @return {@link Icon} with the provided {@link Drawable}.
+ */
+ public Icon fromDrawable(@NonNull Drawable drawable) {
+ int width = drawable.getIntrinsicWidth();
+ int height = drawable.getIntrinsicHeight();
+ return fromDrawable(drawable, width, height);
+ }
+
+ /**
+ * Create an {@link Icon} from a given {@link Drawable}.
+ *
+ * @param drawable A {@link Drawable} object used for creating the {@link Icon}.
+ * @param width An integer greater then zero defining the {@link Icon} width.
+ * @param height An integer greater then zero defining the {@link Icon} height.
+ * @return {@link Icon} with the provided {@link Drawable}.
+ */
+ public Icon fromDrawable(@NonNull Drawable drawable, int width, int height) {
+ if ((width < 0) || (height < 0)) {
+ return null;
}
- private Icon fromInputStream(@NonNull InputStream is) {
- Bitmap bitmap = BitmapFactory.decodeStream(is, null, mOptions);
- return fromBitmap(bitmap);
+ Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ Rect temp = drawable.getBounds();
+ Rect bounds = new Rect(0, 0, width, height);
+ drawable.setBounds(bounds);
+ drawable.draw(canvas);
+ drawable.setBounds(temp);
+ return fromBitmap(bitmap);
+ }
+
+ /**
+ * Create an {@link Icon} using the resource ID of a Bitmap image.
+ *
+ * @param resourceId The resource ID of a Bitmap image.
+ * @return The {@link Icon} that was loaded from the asset or {@code null} if failed to load.
+ */
+ public Icon fromResource(@DrawableRes int resourceId) {
+ Drawable drawable = ContextCompat.getDrawable(mContext, resourceId);
+ Bitmap bitmap;
+ if (drawable instanceof BitmapDrawable) {
+ BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
+ bitmap = bitmapDrawable.getBitmap();
+ } else {
+ if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
+ bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+ } else {
+ bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
+ Bitmap.Config.ARGB_8888);
+ }
+
+ Canvas canvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ drawable.draw(canvas);
}
-
- public Icon fromAsset(@NonNull String assetName) {
- InputStream is;
- try {
- is = mContext.getAssets().open(assetName);
- } catch (IOException e) {
- return null;
- }
- return fromInputStream(is);
+ return fromBitmap(bitmap);
+ }
+
+ /**
+ * Provides an {@link Icon} using the default marker icon used for {@link Marker}.
+ *
+ * @return An {@link Icon} with the default {@link Marker} icon.
+ */
+ public Icon defaultMarker() {
+ if (mDefaultMarker == null) {
+ mDefaultMarker = fromResource(R.drawable.mapbox_marker_icon_default);
}
-
- public Icon fromPath(@NonNull String absolutePath) {
- Bitmap bitmap = BitmapFactory.decodeFile(absolutePath, mOptions);
- return fromBitmap(bitmap);
+ return mDefaultMarker;
+ }
+
+ /**
+ * Provides an {@link Icon} using the default marker icon used for {@link MarkerView}.
+ *
+ * @return An {@link Icon} with the default {@link MarkerView} icon.
+ */
+ public Icon defaultMarkerView() {
+ if (mDefaultMarkerView == null) {
+ mDefaultMarkerView = fromResource(R.drawable.mapbox_markerview_icon_default);
}
-
- public Icon fromFile(@NonNull String fileName) {
- FileInputStream is;
- try {
- is = mContext.openFileInput(fileName);
- } catch (FileNotFoundException e) {
- return null;
- }
- return fromInputStream(is);
+ return mDefaultMarkerView;
+ }
+
+ private Icon fromInputStream(@NonNull InputStream is) {
+ Bitmap bitmap = BitmapFactory.decodeStream(is, null, mOptions);
+ return fromBitmap(bitmap);
+ }
+
+ /**
+ * Creates an {@link Icon} using the name of a Bitmap image in the assets directory.
+ *
+ * @param assetName The name of a Bitmap image in the assets directory.
+ * @return The {@link Icon} that was loaded from the asset or {@code null} if failed to load.
+ */
+ public Icon fromAsset(@NonNull String assetName) {
+ InputStream is;
+ try {
+ is = mContext.getAssets().open(assetName);
+ } catch (IOException ioException) {
+ return null;
}
-
- public static Icon recreate(@NonNull String iconId, @NonNull Bitmap bitmap) {
- return new Icon(iconId, bitmap);
+ return fromInputStream(is);
+ }
+
+ /**
+ * Creates an {@link Icon} using the absolute file path of a Bitmap image.
+ *
+ * @param absolutePath The absolute path of the Bitmap image.
+ * @return The {@link Icon} that was loaded from the absolute path or {@code null} if failed to
+ * load.
+ */
+ public Icon fromPath(@NonNull String absolutePath) {
+ Bitmap bitmap = BitmapFactory.decodeFile(absolutePath, mOptions);
+ return fromBitmap(bitmap);
+ }
+
+ /**
+ * Create an {@link Icon} using the name of a Bitmap image file located in the internal storage.
+ * In particular, this calls {@link Context#openFileInput(String)}.
+ *
+ * @param fileName The name of the Bitmap image file.
+ * @return The {@link Icon} that was loaded from the asset or {@code null} if failed to load.
+ * @see <a href="https://developer.android.com/guide/topics/data/data-storage.html#filesInternal">
+ * Using the Internal Storage</a>
+ */
+ public Icon fromFile(@NonNull String fileName) {
+ FileInputStream is;
+ try {
+ is = mContext.openFileInput(fileName);
+ } catch (FileNotFoundException fileNotFoundException) {
+ return null;
}
+ return fromInputStream(is);
+ }
+
+ /**
+ * Create an {@link Icon} using a previously created icon identifier along with a provided
+ * Bitmap.
+ *
+ * @param iconId The {@link Icon} identifier you'd like to recreate.
+ * @param bitmap a Bitmap used to replace the current one.
+ * @return The {@link Icon} using the new Bitmap.
+ */
+ public static Icon recreate(@NonNull String iconId, @NonNull Bitmap bitmap) {
+ return new Icon(iconId, bitmap);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java
index 9af459e8a0..34d2c31139 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java
@@ -17,264 +17,285 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
import java.lang.ref.WeakReference;
/**
+ * {@code InfoWindow} is a tooltip shown when a {@link Marker} or {@link MarkerView} is tapped. Only
+ * one info window is displayed at a time. When the user clicks on a marker, the currently open info
+ * window will be closed and the new info window will be displayed. If the user clicks the same
+ * marker while its info window is currently open, the info window will be closed.
* <p>
- * InfoWindow is a tooltip shown when a {@link Marker} is tapped.
- * </p>
- * <p>
- * This is a UI element placed over a map at a specific geographic location.
+ * The info window is drawn oriented against the device's screen, centered above its associated
+ * marker by default. The info window anchoring can be adjusted using
+ * {@link MarkerView#setInfoWindowAnchor(float, float)} for {@link MarkerView}. The default info
+ * window contains the title in bold and snippet text below the title. While either the title and
+ * snippet are optional, at least one is required to open the info window.
* </p>
*/
public class InfoWindow {
- private WeakReference<Marker> mBoundMarker;
- private WeakReference<MapboxMap> mMapboxMap;
- protected WeakReference<View> mView;
-
- private float mMarkerHeightOffset;
- private float mMarkerWidthOffset;
- private float mViewWidthOffset;
- private PointF mCoordinates;
- private boolean mIsVisible;
-
- @LayoutRes
- private int mLayoutRes;
-
- InfoWindow(MapView mapView, int layoutResId, MapboxMap mapboxMap) {
- mLayoutRes = layoutResId;
- View view = LayoutInflater.from(mapView.getContext()).inflate(layoutResId, mapView, false);
- initialize(view, mapboxMap);
- }
+ private WeakReference<Marker> boundMarker;
+ private WeakReference<MapboxMap> mapboxMap;
+ protected WeakReference<View> view;
+
+ private float markerHeightOffset;
+ private float markerWidthOffset;
+ private float viewWidthOffset;
+ private PointF coordinates;
+ private boolean isVisible;
+
+ @LayoutRes
+ private int layoutRes;
+
+ InfoWindow(MapView mapView, int layoutResId, MapboxMap mapboxMap) {
+ layoutRes = layoutResId;
+ View view = LayoutInflater.from(mapView.getContext()).inflate(layoutResId, mapView, false);
+ initialize(view, mapboxMap);
+ }
+
+ InfoWindow(View view, MapboxMap mapboxMap) {
+ initialize(view, mapboxMap);
+ }
+
+ private void initialize(View view, MapboxMap mapboxMap) {
+ this.mapboxMap = new WeakReference<>(mapboxMap);
+ isVisible = false;
+ this.view = new WeakReference<>(view);
+
+ view.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ MapboxMap mapboxMap = InfoWindow.this.mapboxMap.get();
+ if (mapboxMap != null) {
+ MapboxMap.OnInfoWindowClickListener onInfoWindowClickListener = mapboxMap.getOnInfoWindowClickListener();
+ boolean handledDefaultClick = false;
+ if (onInfoWindowClickListener != null) {
+ handledDefaultClick = onInfoWindowClickListener.onInfoWindowClick(getBoundMarker());
+ }
+
+ if (!handledDefaultClick) {
+ // default behavior: close it when clicking on the tooltip:
+ close();
+ }
+ }
+ }
+ });
+
+ view.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ MapboxMap mapboxMap = InfoWindow.this.mapboxMap.get();
+ if (mapboxMap != null) {
+ MapboxMap.OnInfoWindowLongClickListener listener = mapboxMap.getOnInfoWindowLongClickListener();
+ if (listener != null) {
+ listener.onInfoWindowLongClick(getBoundMarker());
+ }
+ }
+ return true;
+ }
+ });
+ }
+
+
+ /**
+ * Open the info window at the specified position.
+ *
+ * @param boundMarker The marker on which is hooked the view.
+ * @param position to place the window on the map.
+ * @param offsetX The offset of the view to the position, in pixels. This allows to offset
+ * the view from the object position.
+ * @param offsetY The offset of the view to the position, in pixels. This allows to offset
+ * the view from the object position.
+ * @return this {@link InfoWindow}.
+ */
+ InfoWindow open(MapView mapView, Marker boundMarker, LatLng position, int offsetX, int offsetY) {
+ setBoundMarker(boundMarker);
+
+ MapView.LayoutParams lp = new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT,
+ MapView.LayoutParams.WRAP_CONTENT);
+
+ MapboxMap mapboxMap = this.mapboxMap.get();
+ View view = this.view.get();
+ if (view != null && mapboxMap != null) {
+ view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+
+ // Calculate y-offset for update method
+ markerHeightOffset = -view.getMeasuredHeight() + offsetY;
+ markerWidthOffset = -offsetX;
+
+ // Calculate default Android x,y coordinate
+ coordinates = mapboxMap.getProjection().toScreenLocation(position);
+ float x = coordinates.x - (view.getMeasuredWidth() / 2) + offsetX;
+ float y = coordinates.y - view.getMeasuredHeight() + offsetY;
+
+ if (view instanceof InfoWindowView) {
+ // only apply repositioning/margin for InfoWindowView
+ Resources resources = mapView.getContext().getResources();
+
+ // get right/left popup window
+ float rightSideInfowWindow = x + view.getMeasuredWidth();
+ float leftSideInfoWindow = x;
+
+ // get right/left map view
+ final float mapRight = mapView.getRight();
+ final float mapLeft = mapView.getLeft();
+
+ float marginHorizontal = resources.getDimension(R.dimen.mapbox_infowindow_margin);
+ float tipViewOffset = resources.getDimension(R.dimen.mapbox_infowindow_tipview_width) / 2;
+ float tipViewMarginLeft = view.getMeasuredWidth() / 2 - tipViewOffset;
+
+ boolean outOfBoundsLeft = false;
+ boolean outOfBoundsRight = false;
+
+ // only optimise margins if view is inside current viewport
+ if (coordinates.x >= 0 && coordinates.x <= mapView.getWidth()
+ && coordinates.y >= 0 && coordinates.y <= mapView.getHeight()) {
+
+ // if out of bounds right
+ if (rightSideInfowWindow > mapRight) {
+ outOfBoundsRight = true;
+ x -= rightSideInfowWindow - mapRight;
+ tipViewMarginLeft += rightSideInfowWindow - mapRight + tipViewOffset;
+ rightSideInfowWindow = x + view.getMeasuredWidth();
+ }
+
+ // fit screen left
+ if (leftSideInfoWindow < mapLeft) {
+ outOfBoundsLeft = true;
+ x += mapLeft - leftSideInfoWindow;
+ tipViewMarginLeft -= mapLeft - leftSideInfoWindow + tipViewOffset;
+ leftSideInfoWindow = x;
+ }
+
+ // Add margin right
+ if (outOfBoundsRight && mapRight - rightSideInfowWindow < marginHorizontal) {
+ x -= marginHorizontal - (mapRight - rightSideInfowWindow);
+ tipViewMarginLeft += marginHorizontal - (mapRight - rightSideInfowWindow) - tipViewOffset;
+ leftSideInfoWindow = x;
+ }
+
+ // Add margin left
+ if (outOfBoundsLeft && leftSideInfoWindow - mapLeft < marginHorizontal) {
+ x += marginHorizontal - (leftSideInfoWindow - mapLeft);
+ tipViewMarginLeft -= (marginHorizontal - (leftSideInfoWindow - mapLeft)) - tipViewOffset;
+ }
+ }
- InfoWindow(View view, MapboxMap mapboxMap) {
- initialize(view, mapboxMap);
- }
+ // Adjust tipView
+ InfoWindowView infoWindowView = (InfoWindowView) view;
+ infoWindowView.setTipViewMarginLeft((int) tipViewMarginLeft);
+ }
- private void initialize(View view, MapboxMap mapboxMap) {
- mMapboxMap = new WeakReference<>(mapboxMap);
- mIsVisible = false;
- mView = new WeakReference<>(view);
-
- view.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- MapboxMap mapboxMap = mMapboxMap.get();
- if (mapboxMap != null) {
- MapboxMap.OnInfoWindowClickListener onInfoWindowClickListener = mapboxMap.getOnInfoWindowClickListener();
- boolean handledDefaultClick = false;
- if (onInfoWindowClickListener != null) {
- handledDefaultClick = onInfoWindowClickListener.onInfoWindowClick(getBoundMarker());
- }
-
- if (!handledDefaultClick) {
- // default behavior: close it when clicking on the tooltip:
- close();
- }
- }
- }
- });
-
- view.setOnLongClickListener(new View.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- MapboxMap mapboxMap = mMapboxMap.get();
- if (mapboxMap != null) {
- MapboxMap.OnInfoWindowLongClickListener listener = mapboxMap.getOnInfoWindowLongClickListener();
- if (listener != null) {
- listener.onInfoWindowLongClick(getBoundMarker());
- }
- }
- return true;
- }
- });
- }
+ // set anchor popupwindowview
+ view.setX(x);
+ view.setY(y);
+ // Calculate x-offset for update method
+ viewWidthOffset = x - coordinates.x - offsetX;
- /**
- * open the window at the specified position.
- *
- * @param boundMarker the marker on which is hooked the view
- * @param position to place the window on the map
- * @param offsetX (&offsetY) the offset of the view to the position, in pixels.
- * This allows to offset the view from the object position.
- * @return this infowindow
- */
- InfoWindow open(MapView mapView, Marker boundMarker, LatLng position, int offsetX, int offsetY) {
- setBoundMarker(boundMarker);
-
- MapView.LayoutParams lp = new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT, MapView.LayoutParams.WRAP_CONTENT);
-
- MapboxMap mapboxMap = mMapboxMap.get();
- View view = mView.get();
- if (view != null && mapboxMap != null) {
- view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
-
- // Calculate y-offset for update method
- mMarkerHeightOffset = -view.getMeasuredHeight() + offsetY;
- mMarkerWidthOffset = -offsetX;
-
- // Calculate default Android x,y coordinate
- mCoordinates = mapboxMap.getProjection().toScreenLocation(position);
- float x = mCoordinates.x - (view.getMeasuredWidth() / 2) + offsetX;
- float y = mCoordinates.y - view.getMeasuredHeight() + offsetY;
-
- if (view instanceof InfoWindowView) {
- // only apply repositioning/margin for InfoWindowView
- Resources resources = mapView.getContext().getResources();
-
- // get right/left popup window
- float rightSideInfowWindow = x + view.getMeasuredWidth();
- float leftSideInfoWindow = x;
-
- // get right/left map view
- final float mapRight = mapView.getRight();
- final float mapLeft = mapView.getLeft();
-
- float marginHorizontal = resources.getDimension(R.dimen.infowindow_margin);
- float tipViewOffset = resources.getDimension(R.dimen.infowindow_tipview_width) / 2;
- float tipViewMarginLeft = view.getMeasuredWidth() / 2 - tipViewOffset;
-
- boolean outOfBoundsLeft = false;
- boolean outOfBoundsRight = false;
-
- // if out of bounds right
- if (rightSideInfowWindow > mapRight) {
- outOfBoundsRight = true;
- x -= rightSideInfowWindow - mapRight;
- tipViewMarginLeft += rightSideInfowWindow - mapRight + tipViewOffset;
- rightSideInfowWindow = x + view.getMeasuredWidth();
- }
-
- // fit screen left
- if (leftSideInfoWindow < mapLeft) {
- outOfBoundsLeft = true;
- x += mapLeft - leftSideInfoWindow;
- tipViewMarginLeft -= mapLeft - leftSideInfoWindow + tipViewOffset;
- leftSideInfoWindow = x;
- }
-
- // Add margin right
- if (outOfBoundsRight && mapRight - rightSideInfowWindow < marginHorizontal) {
- x -= marginHorizontal - (mapRight - rightSideInfowWindow);
- tipViewMarginLeft += marginHorizontal - (mapRight - rightSideInfowWindow) - tipViewOffset;
- leftSideInfoWindow = x;
- }
-
- // Add margin left
- if (outOfBoundsLeft && leftSideInfoWindow - mapLeft < marginHorizontal) {
- x += marginHorizontal - (leftSideInfoWindow - mapLeft);
- tipViewMarginLeft -= (marginHorizontal - (leftSideInfoWindow - mapLeft)) - tipViewOffset;
- }
-
- // Adjust tipView
- InfoWindowView infoWindowView = (InfoWindowView) view;
- infoWindowView.setTipViewMarginLeft((int) tipViewMarginLeft);
- }
-
- // set anchor popupwindowview
- view.setX(x);
- view.setY(y);
-
- // Calculate x-offset for update method
- mViewWidthOffset = x - mCoordinates.x - offsetX;
-
- close(); //if it was already opened
- mapView.addView(view, lp);
- mIsVisible = true;
- }
- return this;
+ close(); //if it was already opened
+ mapView.addView(view, lp);
+ isVisible = true;
}
-
- /**
- * Close this InfoWindow if it is visible, otherwise don't do anything.
- *
- * @return this info window
- */
- InfoWindow close() {
- MapboxMap mapboxMap = mMapboxMap.get();
- if (mIsVisible && mapboxMap != null) {
- mIsVisible = false;
- View view = mView.get();
- if (view != null && view.getParent() != null) {
- ((ViewGroup) view.getParent()).removeView(view);
- }
-
- Marker marker = getBoundMarker();
- MapboxMap.OnInfoWindowCloseListener listener = mapboxMap.getOnInfoWindowCloseListener();
- if (listener != null) {
- listener.onInfoWindowClose(marker);
- }
-
- setBoundMarker(null);
- }
- return this;
+ return this;
+ }
+
+ /**
+ * Close this {@link InfoWindow} if it is visible, otherwise calling this will do nothing.
+ *
+ * @return This {@link InfoWindow}
+ */
+ InfoWindow close() {
+ MapboxMap mapboxMap = this.mapboxMap.get();
+ if (isVisible && mapboxMap != null) {
+ isVisible = false;
+ View view = this.view.get();
+ if (view != null && view.getParent() != null) {
+ ((ViewGroup) view.getParent()).removeView(view);
+ }
+
+ Marker marker = getBoundMarker();
+ MapboxMap.OnInfoWindowCloseListener listener = mapboxMap.getOnInfoWindowCloseListener();
+ if (listener != null) {
+ listener.onInfoWindowClose(marker);
+ }
+
+ setBoundMarker(null);
}
-
- /**
- * Constructs the view that is displayed when the InfoWindow opens.
- * This retrieves data from overlayItem and shows it in the tooltip.
- *
- * @param overlayItem the tapped overlay item
- */
- void adaptDefaultMarker(Marker overlayItem, MapboxMap mapboxMap, MapView mapView) {
- View view = mView.get();
- if (view == null) {
- view = LayoutInflater.from(mapView.getContext()).inflate(mLayoutRes, mapView, false);
- initialize(view, mapboxMap);
- }
- mMapboxMap = new WeakReference<>(mapboxMap);
- String title = overlayItem.getTitle();
- TextView titleTextView = ((TextView) view.findViewById(R.id.infowindow_title));
- if (!TextUtils.isEmpty(title)) {
- titleTextView.setText(title);
- titleTextView.setVisibility(View.VISIBLE);
- } else {
- titleTextView.setVisibility(View.GONE);
- }
-
- String snippet = overlayItem.getSnippet();
- TextView snippetTextView = ((TextView) view.findViewById(R.id.infowindow_description));
- if (!TextUtils.isEmpty(snippet)) {
- snippetTextView.setText(snippet);
- snippetTextView.setVisibility(View.VISIBLE);
- } else {
- snippetTextView.setVisibility(View.GONE);
- }
+ return this;
+ }
+
+ /**
+ * Constructs the view that is displayed when the InfoWindow opens. This retrieves data from
+ * overlayItem and shows it in the tooltip.
+ *
+ * @param overlayItem the tapped overlay item
+ */
+ void adaptDefaultMarker(Marker overlayItem, MapboxMap mapboxMap, MapView mapView) {
+ View view = this.view.get();
+ if (view == null) {
+ view = LayoutInflater.from(mapView.getContext()).inflate(layoutRes, mapView, false);
+ initialize(view, mapboxMap);
}
-
- InfoWindow setBoundMarker(Marker boundMarker) {
- mBoundMarker = new WeakReference<>(boundMarker);
- return this;
+ this.mapboxMap = new WeakReference<>(mapboxMap);
+ String title = overlayItem.getTitle();
+ TextView titleTextView = ((TextView) view.findViewById(R.id.infowindow_title));
+ if (!TextUtils.isEmpty(title)) {
+ titleTextView.setText(title);
+ titleTextView.setVisibility(View.VISIBLE);
+ } else {
+ titleTextView.setVisibility(View.GONE);
}
- Marker getBoundMarker() {
- if (mBoundMarker == null) {
- return null;
- }
- return mBoundMarker.get();
+ String snippet = overlayItem.getSnippet();
+ TextView snippetTextView = ((TextView) view.findViewById(R.id.infowindow_description));
+ if (!TextUtils.isEmpty(snippet)) {
+ snippetTextView.setText(snippet);
+ snippetTextView.setVisibility(View.VISIBLE);
+ } else {
+ snippetTextView.setVisibility(View.GONE);
}
+ }
- public void update() {
- MapboxMap mapboxMap = mMapboxMap.get();
- Marker marker = mBoundMarker.get();
- View view = mView.get();
- if (mapboxMap != null && marker != null && view != null) {
- mCoordinates = mapboxMap.getProjection().toScreenLocation(marker.getPosition());
-
- if (view instanceof InfoWindowView) {
- view.setX(mCoordinates.x + mViewWidthOffset - mMarkerWidthOffset);
- } else {
- view.setX(mCoordinates.x - (view.getMeasuredWidth() / 2) - mMarkerWidthOffset);
- }
- view.setY(mCoordinates.y + mMarkerHeightOffset);
- }
- }
+ InfoWindow setBoundMarker(Marker boundMarker) {
+ this.boundMarker = new WeakReference<>(boundMarker);
+ return this;
+ }
- public View getView() {
- return mView != null ? mView.get() : null;
+ Marker getBoundMarker() {
+ if (boundMarker == null) {
+ return null;
}
-
- boolean isVisible() {
- return mIsVisible;
+ return boundMarker.get();
+ }
+
+ /**
+ * Will result in getting this {@link InfoWindow} and updating the view being displayed.
+ */
+ public void update() {
+ MapboxMap mapboxMap = this.mapboxMap.get();
+ Marker marker = boundMarker.get();
+ View view = this.view.get();
+ if (mapboxMap != null && marker != null && view != null) {
+ coordinates = mapboxMap.getProjection().toScreenLocation(marker.getPosition());
+
+ if (view instanceof InfoWindowView) {
+ view.setX(coordinates.x + viewWidthOffset - markerWidthOffset);
+ } else {
+ view.setX(coordinates.x - (view.getMeasuredWidth() / 2) - markerWidthOffset);
+ }
+ view.setY(coordinates.y + markerHeightOffset);
}
+ }
+
+ /**
+ * Retrieve this {@link InfoWindow}'s current view being used.
+ *
+ * @return This {@link InfoWindow}'s current View.
+ */
+ public View getView() {
+ return view != null ? view.get() : null;
+ }
+
+ boolean isVisible() {
+ return isVisible;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowTipView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowTipView.java
index d2afafc59d..abcebfec83 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowTipView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowTipView.java
@@ -12,51 +12,51 @@ import com.mapbox.mapboxsdk.R;
final class InfoWindowTipView extends View {
- private Paint mPaint;
- private Path mPath;
- private int mLineWidth;
-
- public InfoWindowTipView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- mPath = new Path();
- mLineWidth = (int) context.getResources().getDimension(R.dimen.infowindow_line_width);
- mPaint = new Paint();
- mPaint.setColor(Color.WHITE);
- mPaint.setAntiAlias(true);
- mPaint.setStrokeWidth(0.0f);
- mPaint.setStyle(Paint.Style.FILL);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- int height = getMeasuredHeight();
- int width = getMeasuredWidth();
-
- mPath.rewind();
-
- this.mPaint.setColor(Color.WHITE);
- this.mPaint.setAntiAlias(true);
- this.mPaint.setStrokeWidth(0.0f);
- this.mPaint.setStyle(Paint.Style.FILL);
-
- mPath.moveTo(0, 0);
- mPath.lineTo(width, 0);
- mPath.lineTo((width / 2), height);
- mPath.lineTo(0, 0);
- canvas.drawPath(mPath, this.mPaint);
-
- mPath.rewind();
-
- this.mPaint.setColor(Color.parseColor("#C2C2C2"));
- this.mPaint.setAntiAlias(true);
- this.mPaint.setStrokeWidth(mLineWidth);
- this.mPaint.setStyle(Paint.Style.STROKE);
-
- mPath.moveTo(0, 0);
- mPath.lineTo(width / 2, height);
- mPath.lineTo(width, 0);
- canvas.drawPath(mPath, this.mPaint);
- }
+ private Paint mPaint;
+ private Path mPath;
+ private int mLineWidth;
+
+ public InfoWindowTipView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mPath = new Path();
+ mLineWidth = (int) context.getResources().getDimension(R.dimen.mapbox_infowindow_line_width);
+ mPaint = new Paint();
+ mPaint.setColor(Color.WHITE);
+ mPaint.setAntiAlias(true);
+ mPaint.setStrokeWidth(0.0f);
+ mPaint.setStyle(Paint.Style.FILL);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ int height = getMeasuredHeight();
+ int width = getMeasuredWidth();
+
+ mPath.rewind();
+
+ this.mPaint.setColor(Color.WHITE);
+ this.mPaint.setAntiAlias(true);
+ this.mPaint.setStrokeWidth(0.0f);
+ this.mPaint.setStyle(Paint.Style.FILL);
+
+ mPath.moveTo(0, 0);
+ mPath.lineTo(width, 0);
+ mPath.lineTo((width / 2), height);
+ mPath.lineTo(0, 0);
+ canvas.drawPath(mPath, this.mPaint);
+
+ mPath.rewind();
+
+ this.mPaint.setColor(Color.parseColor("#C2C2C2"));
+ this.mPaint.setAntiAlias(true);
+ this.mPaint.setStrokeWidth(mLineWidth);
+ this.mPaint.setStyle(Paint.Style.STROKE);
+
+ mPath.moveTo(0, 0);
+ mPath.lineTo(width / 2, height);
+ mPath.lineTo(width, 0);
+ canvas.drawPath(mPath, this.mPaint);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowView.java
index 80dc5931a7..d1a59aae4e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowView.java
@@ -9,30 +9,30 @@ import com.mapbox.mapboxsdk.R;
class InfoWindowView extends RelativeLayout {
- private InfoWindowTipView mTipView;
-
- public InfoWindowView(Context context) {
- this(context, null);
- }
-
- public InfoWindowView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public InfoWindowView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- initialize(context);
- }
-
- private void initialize(Context context) {
- LayoutInflater.from(context).inflate(R.layout.infowindow_content, this);
- mTipView = (InfoWindowTipView) findViewById(R.id.infowindow_tipview);
- }
-
- void setTipViewMarginLeft(int marginLeft) {
- RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mTipView.getLayoutParams();
- layoutParams.leftMargin = marginLeft;
- // This is a bit of a hack but prevents an occasional gap between the InfoWindow
- layoutParams.topMargin = (int) getResources().getDimension(R.dimen.infowindow_offset);
- }
+ private InfoWindowTipView mTipView;
+
+ public InfoWindowView(Context context) {
+ this(context, null);
+ }
+
+ public InfoWindowView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public InfoWindowView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ initialize(context);
+ }
+
+ private void initialize(Context context) {
+ LayoutInflater.from(context).inflate(R.layout.mapbox_infowindow_content, this);
+ mTipView = (InfoWindowTipView) findViewById(R.id.infowindow_tipview);
+ }
+
+ void setTipViewMarginLeft(int marginLeft) {
+ RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mTipView.getLayoutParams();
+ layoutParams.leftMargin = marginLeft;
+ // This is a bit of a hack but prevents an occasional gap between the InfoWindow
+ layoutParams.topMargin = (int) getResources().getDimension(R.dimen.mapbox_infowindow_offset);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java
index e1f692a6f4..edf118205b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java
@@ -10,206 +10,266 @@ import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
/**
- * Marker is an annotation that shows an icon image at a geographical location.
+ * Marker is an annotation that shows an icon image at a geographical location. The default marker
+ * uses a provided icon. This icon can be customized using {@link IconFactory} to generate an
+ * {@link Icon} using a provided image. Markers are added to the map by first giving a
+ * {@link LatLng} and using {@link MapboxMap#addMarker(MarkerOptions)}. The marker icon will be
+ * centered at this position so it is common to add padding to the icon image before usage.
* <p>
- * An {@link InfoWindow} can be shown when a Marker is pressed
+ * If more customization is needed, we offer {@link MarkerView} which places a {@link View} on top
+ * of the map at a geographical location.
+ * </p>
+ * <p>
+ * Markers are designed to be interactive. They receive click events by default, and are often used
+ * with event listeners to bring up info windows. An {@link InfoWindow} is displayed by default when
+ * either a title or snippet is provided.
* </p>
*/
public class Marker extends Annotation {
- private LatLng position;
- private String snippet;
- private Icon icon;
- private String title;
+ private LatLng position;
+ private String snippet;
+ private Icon icon;
+ private String title;
- private InfoWindow infoWindow;
- private boolean infoWindowShown;
+ private InfoWindow infoWindow;
+ private boolean infoWindowShown;
- private int topOffsetPixels;
- private int rightOffsetPixels;
+ private int topOffsetPixels;
+ private int rightOffsetPixels;
- /**
- * Constructor
- */
- Marker() {
- super();
- }
+ /**
+ * Constructor
+ */
+ Marker() {
+ super();
+ }
- public Marker(BaseMarkerOptions baseMarkerOptions) {
- position = baseMarkerOptions.position;
- snippet = baseMarkerOptions.snippet;
- icon = baseMarkerOptions.icon;
- title = baseMarkerOptions.title;
- }
+ /**
+ * Creates a instance of {@link Marker} using the builder of Marker.
+ *
+ * @param baseMarkerOptions The builder used to construct the Marker.
+ */
+ public Marker(BaseMarkerOptions baseMarkerOptions) {
+ position = baseMarkerOptions.position;
+ snippet = baseMarkerOptions.snippet;
+ icon = baseMarkerOptions.icon;
+ title = baseMarkerOptions.title;
+ }
- Marker(BaseMarkerViewOptions baseMarkerViewOptions) {
- position = baseMarkerViewOptions.position;
- snippet = baseMarkerViewOptions.snippet;
- icon = baseMarkerViewOptions.icon;
- title = baseMarkerViewOptions.title;
- }
+ Marker(BaseMarkerViewOptions baseMarkerViewOptions) {
+ position = baseMarkerViewOptions.position;
+ snippet = baseMarkerViewOptions.snippet;
+ icon = baseMarkerViewOptions.icon;
+ title = baseMarkerViewOptions.title;
+ }
- Marker(LatLng position, Icon icon, String title, String snippet) {
- this.position = position;
- this.icon = icon;
- this.title = title;
- this.snippet = snippet;
- }
+ Marker(LatLng position, Icon icon, String title, String snippet) {
+ this.position = position;
+ this.icon = icon;
+ this.title = title;
+ this.snippet = snippet;
+ }
- public LatLng getPosition() {
- return position;
- }
+ /**
+ * Returns the position of the marker.
+ *
+ * @return A {@link LatLng} object specifying the marker's current position.
+ */
+ public LatLng getPosition() {
+ return position;
+ }
- public String getSnippet() {
- return snippet;
- }
+ /**
+ * Gets the snippet of the marker.
+ *
+ * @return A string containing the marker's snippet.
+ */
+ public String getSnippet() {
+ return snippet;
+ }
- public String getTitle() {
- return title;
- }
+ /**
+ * Gets the snippet of the marker.
+ *
+ * @return A string containing the marker's snippet.
+ */
+ public String getTitle() {
+ return title;
+ }
- /**
- * Do not use this method. Used internally by the SDK.
- */
- public void hideInfoWindow() {
- if (infoWindow != null) {
- infoWindow.close();
- }
- infoWindowShown = false;
+ /**
+ * Do not use this method, used internally by the SDK.
+ */
+ public void hideInfoWindow() {
+ if (infoWindow != null) {
+ infoWindow.close();
}
+ infoWindowShown = false;
+ }
- /**
- * Do not use this method. Used internally by the SDK.
- *
- * @return true if the infoWindow is shown
- */
- public boolean isInfoWindowShown() {
- return infoWindowShown;
- }
+ /**
+ * Do not use this method, used internally by the SDK.
+ *
+ * @return true if the infoWindow is shown
+ */
+ public boolean isInfoWindowShown() {
+ return infoWindowShown;
+ }
- /**
- * Sets the position.
- *
- * @param position new position
- */
- public void setPosition(LatLng position) {
- this.position = position;
- MapboxMap map = getMapboxMap();
- if (map != null) {
- map.updateMarker(this);
- }
+ /**
+ * Sets the location of the marker.
+ *
+ * @param position A {@link LatLng} defining the marker position.
+ */
+ public void setPosition(LatLng position) {
+ this.position = position;
+ MapboxMap map = getMapboxMap();
+ if (map != null) {
+ map.updateMarker(this);
}
+ }
- public void setSnippet(String snippet) {
- this.snippet = snippet;
- refreshInfoWindowContent();
- }
+ /**
+ * Sets the snippet of the marker.
+ *
+ * @param snippet A String used in the marker info window. If {@code null}, the snippet is
+ * cleared.
+ */
+ public void setSnippet(String snippet) {
+ this.snippet = snippet;
+ refreshInfoWindowContent();
+ }
- /**
- * Sets the icon.
- *
- * @param icon The icon to be used as Marker image
- */
- public void setIcon(@Nullable Icon icon) {
- this.icon = icon;
- MapboxMap map = getMapboxMap();
- if (map != null) {
- map.updateMarker(this);
- }
+ /**
+ * Sets the icon of the marker.
+ *
+ * @param icon The {@link Icon} to be used as Marker image
+ */
+ public void setIcon(@Nullable Icon icon) {
+ this.icon = icon;
+ MapboxMap map = getMapboxMap();
+ if (map != null) {
+ map.updateMarker(this);
}
+ }
- public Icon getIcon() {
- return icon;
- }
+ /**
+ * Gets the {@link Icon} currently used for the marker. If no Icon was set for the marker, the
+ * default icon will be returned.
+ *
+ * @return The {@link Icon} the marker is using.
+ */
+ public Icon getIcon() {
+ return icon;
+ }
- public void setTitle(String title) {
- this.title = title;
- refreshInfoWindowContent();
- }
+ /**
+ * Sets the title of the marker.
+ *
+ * @param title A String used in the marker info window. If {@code null}, the title is
+ * cleared.
+ */
+ public void setTitle(String title) {
+ this.title = title;
+ refreshInfoWindowContent();
+ }
- @Nullable
- public InfoWindow getInfoWindow() {
- return infoWindow;
- }
+ /**
+ * Gets the {@link InfoWindow} the marker is using. If the marker hasn't had an info window
+ * defined, this will return {@code null}.
+ *
+ * @return The info window the marker is using.
+ */
+ @Nullable
+ public InfoWindow getInfoWindow() {
+ return infoWindow;
+ }
- /**
- * Update only for default Marker's InfoWindow content for Title and Snippet
- */
- private void refreshInfoWindowContent() {
- if (isInfoWindowShown() && mapView != null && mapboxMap != null && mapboxMap.getInfoWindowAdapter() == null) {
- InfoWindow infoWindow = getInfoWindow(mapView);
- if (mapView.getContext() != null) {
- infoWindow.adaptDefaultMarker(this, mapboxMap, mapView);
- }
- MapboxMap map = getMapboxMap();
- if (map != null) {
- map.updateMarker(this);
- }
- infoWindow.update();
- }
+ /**
+ * Update only for default Marker's InfoWindow content for Title and Snippet
+ */
+ private void refreshInfoWindowContent() {
+ if (isInfoWindowShown() && mapView != null && mapboxMap != null && mapboxMap.getInfoWindowAdapter() == null) {
+ InfoWindow infoWindow = getInfoWindow(mapView);
+ if (mapView.getContext() != null) {
+ infoWindow.adaptDefaultMarker(this, mapboxMap, mapView);
+ }
+ MapboxMap map = getMapboxMap();
+ if (map != null) {
+ map.updateMarker(this);
+ }
+ infoWindow.update();
}
+ }
- /**
- * Do not use this method. Used internally by the SDK.
- *
- * @param mapboxMap the hosting mapbox map
- * @param mapView the hosting map view
- * @return the info window that was shown
- */
- public InfoWindow showInfoWindow(@NonNull MapboxMap mapboxMap, @NonNull MapView mapView) {
- setMapboxMap(mapboxMap);
- setMapView(mapView);
- MapboxMap.InfoWindowAdapter infoWindowAdapter = getMapboxMap().getInfoWindowAdapter();
- if (infoWindowAdapter != null) {
- // end developer is using a custom InfoWindowAdapter
- View content = infoWindowAdapter.getInfoWindow(this);
- if (content != null) {
- infoWindow = new InfoWindow(content, mapboxMap);
- showInfoWindow(infoWindow, mapView);
- return infoWindow;
- }
- }
-
- InfoWindow infoWindow = getInfoWindow(mapView);
- if (mapView.getContext() != null) {
- infoWindow.adaptDefaultMarker(this, mapboxMap, mapView);
- }
- return showInfoWindow(infoWindow, mapView);
+ /**
+ * Do not use this method, used internally by the SDK. Use {@link MapboxMap#selectMarker(Marker)}
+ * if you want to programmatically display the markers info window.
+ *
+ * @param mapboxMap The hosting mapbox map.
+ * @param mapView The hosting map view.
+ * @return The info window that was shown.
+ */
+ public InfoWindow showInfoWindow(@NonNull MapboxMap mapboxMap, @NonNull MapView mapView) {
+ setMapboxMap(mapboxMap);
+ setMapView(mapView);
+ MapboxMap.InfoWindowAdapter infoWindowAdapter = getMapboxMap().getInfoWindowAdapter();
+ if (infoWindowAdapter != null) {
+ // end developer is using a custom InfoWindowAdapter
+ View content = infoWindowAdapter.getInfoWindow(this);
+ if (content != null) {
+ infoWindow = new InfoWindow(content, mapboxMap);
+ showInfoWindow(infoWindow, mapView);
+ return infoWindow;
+ }
}
- private InfoWindow showInfoWindow(InfoWindow iw, MapView mapView) {
- iw.open(mapView, this, getPosition(), rightOffsetPixels, topOffsetPixels);
- infoWindowShown = true;
- return iw;
+ InfoWindow infoWindow = getInfoWindow(mapView);
+ if (mapView.getContext() != null) {
+ infoWindow.adaptDefaultMarker(this, mapboxMap, mapView);
}
+ return showInfoWindow(infoWindow, mapView);
+ }
- private InfoWindow getInfoWindow(@NonNull MapView mapView) {
- if (infoWindow == null && mapView.getContext() != null) {
- infoWindow = new InfoWindow(mapView, R.layout.infowindow_view, getMapboxMap());
- }
- return infoWindow;
- }
+ private InfoWindow showInfoWindow(InfoWindow iw, MapView mapView) {
+ iw.open(mapView, this, getPosition(), rightOffsetPixels, topOffsetPixels);
+ infoWindowShown = true;
+ return iw;
+ }
- /**
- * Do not use this method. Used internally by the SDK.
- *
- * @param topOffsetPixels the top offset pixels.
- */
- public void setTopOffsetPixels(int topOffsetPixels) {
- this.topOffsetPixels = topOffsetPixels;
+ private InfoWindow getInfoWindow(@NonNull MapView mapView) {
+ if (infoWindow == null && mapView.getContext() != null) {
+ infoWindow = new InfoWindow(mapView, R.layout.mapbox_infowindow_view, getMapboxMap());
}
+ return infoWindow;
+ }
- /**
- * Do not use this method. Used internally by the SDK.
- *
- * @param rightOffsetPixels the right offset pixels.
- */
- public void setRightOffsetPixels(int rightOffsetPixels) {
- this.rightOffsetPixels = rightOffsetPixels;
- }
+ /**
+ * Do not use this method, used internally by the SDK.
+ *
+ * @param topOffsetPixels the top offset pixels.
+ */
+ public void setTopOffsetPixels(int topOffsetPixels) {
+ this.topOffsetPixels = topOffsetPixels;
+ }
- @Override
- public String toString() {
- return "Marker [position[" + getPosition() + "]]";
- }
+ /**
+ * Do not use this method, used internally by the SDK.
+ *
+ * @param rightOffsetPixels the right offset pixels.
+ */
+ public void setRightOffsetPixels(int rightOffsetPixels) {
+ this.rightOffsetPixels = rightOffsetPixels;
+ }
+
+ /**
+ * Returns a String with the marker position.
+ *
+ * @return A String with the marker position.
+ */
+ @Override
+ public String toString() {
+ return "Marker [position[" + getPosition() + "]]";
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java
index 328ee1894c..49d4867801 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java
@@ -7,14 +7,13 @@ import android.os.Parcelable;
import com.mapbox.mapboxsdk.exceptions.InvalidMarkerPositionException;
import com.mapbox.mapboxsdk.geometry.LatLng;
-
/**
* <p>
- * Builder for composing {@link com.mapbox.mapboxsdk.annotations.Marker} objects.
+ * Builder for composing {@link Marker} objects. See {@link Marker} for additional information.
* </p>
* <h3>Example</h3>
* <pre>
- * mMapView.addMarker(new MarkerOptions()
+ * mapView.addMarker(new MarkerOptions()
* .title("Intersection")
* .snippet("H St NW with 15th St NW")
* .position(new LatLng(38.9002073, -77.03364419)));
@@ -22,108 +21,168 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
*/
public final class MarkerOptions extends BaseMarkerOptions<Marker, MarkerOptions> implements Parcelable {
- public MarkerOptions() {
+ /**
+ * Defines options for a Marker.
+ */
+ public MarkerOptions() {
+ }
+
+ protected MarkerOptions(Parcel in) {
+ position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
+ snippet(in.readString());
+ title(in.readString());
+ if (in.readByte() != 0) {
+ // this means we have an icon
+ String iconId = in.readString();
+ Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
+ Icon icon = new Icon(iconId, iconBitmap);
+ icon(icon);
}
-
- protected MarkerOptions(Parcel in) {
- position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
- snippet(in.readString());
- title(in.readString());
- if (in.readByte() != 0) {
- // this means we have an icon
- String iconId = in.readString();
- Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
- Icon icon = new Icon(iconId, iconBitmap);
- icon(icon);
- }
+ }
+
+ @Override
+ public MarkerOptions getThis() {
+ return this;
+ }
+
+ /**
+ * Describe the kinds of special objects contained in this Parcelable's
+ * marshalled representation.
+ *
+ * @return integer 0.
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Flatten this object in to a Parcel.
+ *
+ * @param out The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written. May be 0 or
+ * {@link #PARCELABLE_WRITE_RETURN_VALUE}.
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(getPosition(), flags);
+ out.writeString(getSnippet());
+ out.writeString(getTitle());
+ Icon icon = getIcon();
+ out.writeByte((byte) (icon != null ? 1 : 0));
+ if (icon != null) {
+ out.writeString(getIcon().getId());
+ out.writeParcelable(getIcon().getBitmap(), flags);
}
-
- @Override
- public MarkerOptions getThis() {
- return this;
- }
-
- @Override
- public int describeContents() {
- return 0;
+ }
+
+ /**
+ * Do not use this method. Used internally by the SDK.
+ *
+ * @return Marker The build marker
+ */
+ public Marker getMarker() {
+ if (position == null) {
+ throw new InvalidMarkerPositionException();
}
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(getPosition(), flags);
- out.writeString(getSnippet());
- out.writeString(getTitle());
- Icon icon = getIcon();
- out.writeByte((byte) (icon != null ? 1 : 0));
- if (icon != null) {
- out.writeString(getIcon().getId());
- out.writeParcelable(getIcon().getBitmap(), flags);
- }
- }
-
- /**
- * Do not use this method. Used internally by the SDK.
- *
- * @return Marker The build marker
- */
- public Marker getMarker() {
- if (position == null) {
- throw new InvalidMarkerPositionException();
- }
-
- return new Marker(position, icon, title, snippet);
- }
+ return new Marker(position, icon, title, snippet);
+ }
+
+ /**
+ * Returns the position set for this {@link MarkerOptions} object.
+ *
+ * @return A {@link LatLng} object specifying the marker's current position.
+ */
+ public LatLng getPosition() {
+ return position;
+ }
+
+ /**
+ * Gets the snippet set for this {@link MarkerOptions} object.
+ *
+ * @return A string containing the marker's snippet.
+ */
+ public String getSnippet() {
+ return snippet;
+ }
+
+ /**
+ * Gets the title set for this {@link MarkerOptions} object.
+ *
+ * @return A string containing the marker's title.
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * Gets the custom icon set for this {@link MarkerOptions} object.
+ *
+ * @return A {@link Icon} object that the marker is using. If the icon wasn't set, default icon
+ * will return.
+ */
+ public Icon getIcon() {
+ return icon;
+ }
+
+ public static final Parcelable.Creator<MarkerOptions> CREATOR =
+ new Parcelable.Creator<MarkerOptions>() {
+ public MarkerOptions createFromParcel(Parcel in) {
+ return new MarkerOptions(in);
+ }
+
+ public MarkerOptions[] newArray(int size) {
+ return new MarkerOptions[size];
+ }
+ };
- public LatLng getPosition() {
- return position;
+ /**
+ * Compares this {@link MarkerOptions} object with another {@link MarkerOptions} and
+ * determines if their properties match.
+ *
+ * @param o Another {@link MarkerOptions} to compare with this object.
+ * @return True if marker properties match this {@link MarkerOptions} object.
+ * Else, false.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
}
-
- public String getSnippet() {
- return snippet;
+ if (o == null || getClass() != o.getClass()) {
+ return false;
}
- public String getTitle() {
- return title;
- }
+ MarkerOptions marker = (MarkerOptions) o;
- public Icon getIcon() {
- return icon;
+ if (getPosition() != null ? !getPosition().equals(marker.getPosition()) : marker.getPosition() != null) {
+ return false;
}
-
- public static final Parcelable.Creator<MarkerOptions> CREATOR
- = new Parcelable.Creator<MarkerOptions>() {
- public MarkerOptions createFromParcel(Parcel in) {
- return new MarkerOptions(in);
- }
-
- public MarkerOptions[] newArray(int size) {
- return new MarkerOptions[size];
- }
- };
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- MarkerOptions marker = (MarkerOptions) o;
-
- if (getPosition() != null ? !getPosition().equals(marker.getPosition()) : marker.getPosition() != null)
- return false;
- if (getSnippet() != null ? !getSnippet().equals(marker.getSnippet()) : marker.getSnippet() != null)
- return false;
- if (getIcon() != null ? !getIcon().equals(marker.getIcon()) : marker.getIcon() != null)
- return false;
- return !(getTitle() != null ? !getTitle().equals(marker.getTitle()) : marker.getTitle() != null);
+ if (getSnippet() != null ? !getSnippet().equals(marker.getSnippet()) : marker.getSnippet() != null) {
+ return false;
}
-
- @Override
- public int hashCode() {
- int result = 1;
- result = 31 * result + (getPosition() != null ? getPosition().hashCode() : 0);
- result = 31 * result + (getSnippet() != null ? getSnippet().hashCode() : 0);
- result = 31 * result + (getIcon() != null ? getIcon().hashCode() : 0);
- result = 31 * result + (getTitle() != null ? getTitle().hashCode() : 0);
- return result;
+ if (getIcon() != null ? !getIcon().equals(marker.getIcon()) : marker.getIcon() != null) {
+ return false;
}
+ return !(getTitle() != null ? !getTitle().equals(marker.getTitle()) : marker.getTitle() != null);
+ }
+
+ /**
+ * Gives an integer which can be used as the bucket number for storing elements of the set/map.
+ * This bucket number is the address of the element inside the set/map. There's no guarantee
+ * that this hash value will be consistent between different Java implementations, or even
+ * between different execution runs of the same program.
+ *
+ * @return integer value you can use for storing element.
+ */
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + (getPosition() != null ? getPosition().hashCode() : 0);
+ result = 31 * result + (getSnippet() != null ? getSnippet().hashCode() : 0);
+ result = 31 * result + (getIcon() != null ? getIcon().hashCode() : 0);
+ result = 31 * result + (getTitle() != null ? getTitle().hashCode() : 0);
+ return result;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
index 175fd57da4..c1b643eb4c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
@@ -8,389 +8,402 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapboxMap;
/**
- * MarkerView is an annotation that shows an View at a geographical location.
+ * MarkerView is an annotation that shows a {@link android.view.View} at a geographical location. The
+ * default marker uses a provided icon. This icon can be customized using {@link IconFactory} to
+ * generate an {@link Icon} using a provided image. MarkerViews are added to the map by first giving
+ * a {@link LatLng} and using {@link MapboxMap#addMarker(BaseMarkerViewOptions)}. The marker view icon
+ * by default is anchored at the center bottom.
* <p>
- * This class uses {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter} to adapt a
+ * If many markers are needed to be displayed on the map at once we suggest using {@link Marker}
+ * instead. This class uses {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter} to adapt a
* MarkerView model to an Android SDK {@link android.view.View} object.
* </p>
* <p>
- * An {@link InfoWindow} can be shown when a MarkerView is pressed
+ * MarkerViews are designed to be interactive. They receive click events by default, and are often
+ * used with event listeners to bring up info windows. An {@link InfoWindow} is displayed by default
+ * when either a title or snippet is provided.
* </p>
*/
public class MarkerView extends Marker {
- private MarkerViewManager markerViewManager;
-
- private float width;
- private float height;
-
- private float anchorU;
- private float anchorV;
-
- private float offsetX = MapboxConstants.UNMEASURED;
- private float offsetY = MapboxConstants.UNMEASURED;
-
- private float infoWindowAnchorU;
- private float infoWindowAnchorV;
-
- private boolean flat;
- private boolean visible = true;
-
- private float tiltValue;
- private float rotation;
- private float alpha = 1;
-
- private Icon markerViewIcon;
-
- private boolean selected;
-
-
- /**
- * Publicly hidden default constructor
- */
- MarkerView() {
- }
-
- /**
- * Creates a instance of MarkerView using the builder of MarkerView
- *
- * @param baseMarkerViewOptions the builder used to construct the MarkerView
- */
- public MarkerView(BaseMarkerViewOptions baseMarkerViewOptions) {
- super(baseMarkerViewOptions);
- this.alpha = baseMarkerViewOptions.getAlpha();
- this.anchorU = baseMarkerViewOptions.getAnchorU();
- this.anchorV = baseMarkerViewOptions.getAnchorV();
- this.infoWindowAnchorU = baseMarkerViewOptions.getInfoWindowAnchorU();
- this.infoWindowAnchorV = baseMarkerViewOptions.getInfoWindowAnchorV();
- this.flat = baseMarkerViewOptions.isFlat();
- this.rotation = baseMarkerViewOptions.getRotation();
- this.selected = baseMarkerViewOptions.selected;
- }
-
- float getWidth() {
- return width;
- }
-
- void setWidth(float width) {
- this.width = width;
- }
-
- float getHeight() {
- return height;
- }
-
- void setHeight(float height) {
- this.height = height;
- }
-
- /**
- * Specifies the anchor being set on a particular point point of the MarkerView.
- * <p>
- * The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0)
- * is the top-left corner of the image, and (1, 1) is the bottom-right corner.
- * </p>
- *
- * @param u u-coordinate of the anchor, as a ratio of the image width (in the range [0, 1])
- * @param v v-coordinate of the anchor, as a ratio of the image height (in the range [0, 1])
- */
- public void setAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
- this.anchorU = u;
- this.anchorV = v;
- setOffset(-1, -1);
- }
-
- /**
- * Get the horizontal distance, normalized to [0, 1], of the anchor from the left edge.
- *
- * @return the u-value of the anchor
- */
- public float getAnchorU() {
- return anchorU;
- }
-
- /**
- * Get the vertical distance, normalized to [0, 1], of the anchor from the top edge.
- *
- * @return the v-value of the anchor
- */
- public float getAnchorV() {
- return anchorV;
- }
-
- /**
- * Internal method to set the calculated offset.
- * <p>
- * These are calculated based on the View bounds and the provided anchor.
- * </p>
- *
- * @param x the x-value of the offset
- * @param y the y-value of the offset
- */
- void setOffset(float x, float y) {
- offsetX = x;
- offsetY = y;
- }
-
- /**
- * Internal method to get the horizontal calculated offset
- *
- * @return the calculated horizontal offset
- */
- float getOffsetX() {
- return offsetX;
- }
-
- /**
- * Internal method to get the vertical calculated offset
- *
- * @return the calculated vertical offset
- */
- float getOffsetY() {
- return offsetY;
- }
-
- /**
- * Specifies the anchor point of the info window on the View of the MarkerView.
- * <p>
- * This is specified in the same coordinate system as the anchor.
- * </p>
- * <p>
- * The default is the top middle of the View.
- * </p>
- *
- * @param u u-coordinate of the info window anchor, as a ratio of the image width (in the range [0, 1])
- * @param v v-coordinate of the info window anchor, as a ratio of the image height (in the range [0, 1])
- * @see #setAnchor(float, float) for more details.
- */
- public void setInfoWindowAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
- this.infoWindowAnchorU = u;
- this.infoWindowAnchorV = v;
- }
-
- /**
- * Get the horizontal distance, normalized to [0, 1], of the info window anchor from the left edge.
- *
- * @return the u value of the InfoWindow anchor.
- */
- public float getInfoWindowAnchorU() {
- return infoWindowAnchorU;
- }
-
- /**
- * Get the vertical distance, normalized to [0, 1], of the info window anchor from the top edge.
- *
- * @return the v value of the InfoWindow anchor.
- */
- public float getInfoWindowAnchorV() {
- return infoWindowAnchorV;
- }
-
- /**
- * Get the flat state of a MarkerView.
- *
- * @return true is the MarkerView is flat; false is the MarkerView is billboard
- */
- public boolean isFlat() {
- return flat;
- }
-
- /**
- * Sets whether this marker should be flat against the map true or a billboard facing the camera false.
- *
- * @param flat the flat state of the MarkerView
- */
- public void setFlat(boolean flat) {
- this.flat = flat;
- }
-
- /**
- * Internal method to get the current tilted value of a MarkerView.
- *
- * @return the tilted value
- */
- float getTilt() {
- return tiltValue;
- }
-
- /**
- * Internal method to set the current titled value of a MarkerView.
- *
- * @param tiltValue the tilted value to set
- */
- void setTilt(@FloatRange(from = 0.0, to = MapboxConstants.MAXIMUM_TILT) float tiltValue) {
- this.tiltValue = tiltValue;
- }
-
- /**
- * Set the visible state of a MarkerView.
- *
- * @param visible true will make the MarkerView visible, false will hide the MarkerViews
- */
- public void setVisible(boolean visible) {
- this.visible = visible;
- if (markerViewManager != null) {
- markerViewManager.animateVisible(this, visible);
- }
- }
-
- /**
- * Returns the visible state of the MarkerView.
- *
- * @return the visible state
- */
- public boolean isVisible() {
- return visible;
- }
-
- /**
- * Set the rotation value of the MarkerView in degrees.
- * <p>
- * Input will be limited to 0 - 360 degrees
- * </p>
- * <p>
- * This will result in animating the rotation of the MarkerView using an rotation animator
- * from current value to the provided parameter value.
- * </p>
- *
- * @param rotation the rotation value to animate to
- */
- public void setRotation(float rotation) {
- // limit to 0 - 360 degrees
- float newRotation = rotation;
- while (newRotation > 360) {
- newRotation -= 360;
- }
- while (newRotation < 0) {
- newRotation += 360;
- }
-
- // calculate new direction
- float diff = newRotation - this.rotation;
- if (diff > 180.0f) {
- diff -= 360.0f;
- } else if (diff < -180.0f) {
- diff += 360.f;
- }
-
- this.rotation = newRotation;
- if (markerViewManager != null) {
- markerViewManager.animateRotationBy(this, diff);
- }
- }
-
- /**
- * Get the rotation value of the MarkerView.
- *
- * @return the rotation value
- */
- public float getRotation() {
- return rotation;
- }
-
- /**
- * Get the alpha value of the MarkerView.
- *
- * @return the alpha value
- */
- public float getAlpha() {
- return alpha;
- }
-
- /**
- * Set the alpha value of the MarkerView.
- * <p>
- * This will result in animating the alpha of the MarkerView using an alpha animator
- * from current value to the provided parameter value.
- * </p>
- *
- * @param alpha the alpha value to animate to
- */
- public void setAlpha(@FloatRange(from = 0.0, to = 255.0) float alpha) {
- this.alpha = alpha;
- if (markerViewManager != null) {
- markerViewManager.animateAlpha(this, alpha);
- }
- }
-
- /**
- * Set the icon of the MarkerView.
- *
- * @param icon the icon to be used as Marker image
- */
- @Override
- public void setIcon(@Nullable Icon icon) {
- if (icon != null) {
- markerViewIcon = IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID, icon.getBitmap());
- }
- Icon transparentIcon = IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID,
- IconFactory.ICON_MARKERVIEW_BITMAP);
- if (markerViewManager != null) {
- markerViewManager.updateIcon(this);
- }
- super.setIcon(transparentIcon);
- }
-
- @Override
- public void setPosition(LatLng position) {
- super.setPosition(position);
- if (markerViewManager != null) {
- markerViewManager.update();
- }
- }
-
- public boolean isSelected() {
- return selected;
- }
-
- /**
- * For internal use only, use {@link MapboxMap#selectMarker(Marker)} instead.
- */
- void setSelected(boolean selected) {
- this.selected = selected;
- }
-
- /**
- * Get the icon of the MarkerView.
- *
- * @return the icon use as Marker image
- */
- @Override
- public Icon getIcon() {
- return markerViewIcon;
- }
-
- /**
- * Set the MapboxMap associated tot the MapView containing the MarkerView.
- * <p>
- * This method is used to instantiate the MarkerView and provide an instance of {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter}
- * </p>
- * <p>
- * This method is used to notify that a MarkerView is no longer active by setting a null value.
- * </p>
- *
- * @param mapboxMap the MapboxMap instances
- */
- @Override
- public void setMapboxMap(MapboxMap mapboxMap) {
- super.setMapboxMap(mapboxMap);
- if(mapboxMap!=null) {
- if (isFlat()) {
- // initial tilt value if MapboxMap is started with a tilt attribute
- tiltValue = (float) mapboxMap.getCameraPosition().tilt;
- }
-
- markerViewManager = mapboxMap.getMarkerViewManager();
- }
- }
-
- /**
- * Get the String representation of a MarkerView.
- *
- * @return the String representation
- */
- @Override
- public String toString() {
- return "MarkerView [position[" + getPosition() + "]]";
- }
+ private MarkerViewManager markerViewManager;
+
+ private float width;
+ private float height;
+
+ private float anchorU;
+ private float anchorV;
+
+ private float offsetX = MapboxConstants.UNMEASURED;
+ private float offsetY = MapboxConstants.UNMEASURED;
+
+ private float infoWindowAnchorU;
+ private float infoWindowAnchorV;
+
+ private boolean flat;
+ private boolean visible = true;
+
+ private float tiltValue;
+ private float rotation;
+ private float alpha = 1;
+
+ private Icon markerViewIcon;
+
+ private boolean selected;
+
+
+ /**
+ * Publicly hidden default constructor
+ */
+ MarkerView() {
+ }
+
+ /**
+ * Creates a instance of MarkerView using the builder of MarkerView
+ *
+ * @param baseMarkerViewOptions the builder used to construct the MarkerView
+ */
+ public MarkerView(BaseMarkerViewOptions baseMarkerViewOptions) {
+ super(baseMarkerViewOptions);
+ this.alpha = baseMarkerViewOptions.getAlpha();
+ this.anchorU = baseMarkerViewOptions.getAnchorU();
+ this.anchorV = baseMarkerViewOptions.getAnchorV();
+ this.infoWindowAnchorU = baseMarkerViewOptions.getInfoWindowAnchorU();
+ this.infoWindowAnchorV = baseMarkerViewOptions.getInfoWindowAnchorV();
+ this.flat = baseMarkerViewOptions.isFlat();
+ this.rotation = baseMarkerViewOptions.getRotation();
+ this.selected = baseMarkerViewOptions.selected;
+ }
+
+ float getWidth() {
+ return width;
+ }
+
+ void setWidth(float width) {
+ this.width = width;
+ }
+
+ float getHeight() {
+ return height;
+ }
+
+ void setHeight(float height) {
+ this.height = height;
+ }
+
+ /**
+ * Specifies the anchor being set on a particular point of the MarkerView.
+ * <p>
+ * The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0)
+ * is the top-left corner of the image, and (1, 1) is the bottom-right corner.
+ * </p>
+ *
+ * @param u u-coordinate of the anchor, as a ratio of the image width (in the range [0, 1]).
+ * @param v v-coordinate of the anchor, as a ratio of the image height (in the range [0, 1]).
+ */
+ public void setAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
+ this.anchorU = u;
+ this.anchorV = v;
+ setOffset(-1, -1);
+ }
+
+ /**
+ * Get the horizontal distance, normalized to [0, 1], of the anchor from the left edge.
+ *
+ * @return The u-value of the anchor.
+ */
+ public float getAnchorU() {
+ return anchorU;
+ }
+
+ /**
+ * Get the vertical distance, normalized to [0, 1], of the anchor from the top edge.
+ *
+ * @return the v-value of the anchor.
+ */
+ public float getAnchorV() {
+ return anchorV;
+ }
+
+ /**
+ * Internal method to set the calculated offset.
+ * <p>
+ * These are calculated based on the View bounds and the provided anchor.
+ * </p>
+ *
+ * @param x the x-value of the offset.
+ * @param y the y-value of the offset.
+ */
+ void setOffset(float x, float y) {
+ offsetX = x;
+ offsetY = y;
+ }
+
+ /**
+ * Internal method to get the horizontal calculated offset.
+ *
+ * @return the calculated horizontal offset.
+ */
+ float getOffsetX() {
+ return offsetX;
+ }
+
+ /**
+ * Internal method to get the vertical calculated offset.
+ *
+ * @return the calculated vertical offset.
+ */
+ float getOffsetY() {
+ return offsetY;
+ }
+
+ /**
+ * Specifies the anchor point of the info window on the View of the MarkerView.
+ * <p>
+ * The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0)
+ * is the top-left corner of the image, and (1, 1) is the bottom-right corner.
+ * </p>
+ * <p>
+ * The default is the top middle of the View.
+ * </p>
+ *
+ * @param u u-coordinate of the info window anchor, as a ratio of the image width (in the range [0, 1]).
+ * @param v v-coordinate of the info window anchor, as a ratio of the image height (in the range [0, 1]).
+ * @see #setAnchor(float, float) for more details.
+ */
+ public void setInfoWindowAnchor(@FloatRange(from = 0.0, to = 1.0) float u,
+ @FloatRange(from = 0.0, to = 1.0) float v) {
+ this.infoWindowAnchorU = u;
+ this.infoWindowAnchorV = v;
+ }
+
+ /**
+ * Get the horizontal distance, normalized to [0, 1], of the info window anchor from the left edge.
+ *
+ * @return the u value of the InfoWindow anchor.
+ */
+ public float getInfoWindowAnchorU() {
+ return infoWindowAnchorU;
+ }
+
+ /**
+ * Get the vertical distance, normalized to [0, 1], of the info window anchor from the top edge.
+ *
+ * @return the v value of the InfoWindow anchor.
+ */
+ public float getInfoWindowAnchorV() {
+ return infoWindowAnchorV;
+ }
+
+ /**
+ * Get the flat state of a MarkerView.
+ *
+ * @return true if the MarkerView is flat; false if the MarkerView is billboard.
+ */
+ public boolean isFlat() {
+ return flat;
+ }
+
+ /**
+ * Sets whether this MarkerView should be flat against the map (true) or a billboard facing the
+ * camera (false).
+ *
+ * @param flat the flat state of the MarkerView.
+ */
+ public void setFlat(boolean flat) {
+ this.flat = flat;
+ }
+
+ /**
+ * Internal method to get the current tilted value of a MarkerView.
+ *
+ * @return the tilted value.
+ */
+ float getTilt() {
+ return tiltValue;
+ }
+
+ /**
+ * Internal method to set the current titled value of a MarkerView.
+ *
+ * @param tiltValue the tilted value to set.
+ */
+ void setTilt(@FloatRange(from = 0.0, to = MapboxConstants.MAXIMUM_TILT) float tiltValue) {
+ this.tiltValue = tiltValue;
+ }
+
+ /**
+ * Set the visible state of a MarkerView.
+ *
+ * @param visible true will make the MarkerView visible, false will hide the MarkerView.
+ */
+ public void setVisible(boolean visible) {
+ this.visible = visible;
+ if (markerViewManager != null) {
+ markerViewManager.animateVisible(this, visible);
+ }
+ }
+
+ /**
+ * Returns the visible state of the MarkerView.
+ *
+ * @return the visible state.
+ */
+ public boolean isVisible() {
+ return visible;
+ }
+
+ /**
+ * Set the rotation value of the MarkerView in degrees.
+ * <p>
+ * Input will be limited to 0 - 360 degrees.
+ * </p>
+ * <p>
+ * This will result in animating the rotation of the MarkerView using an rotation animator
+ * from current value to the provided parameter value.
+ * </p>
+ *
+ * @param rotation the rotation value to animate to.
+ */
+ public void setRotation(float rotation) {
+ // limit to 0 - 360 degrees
+ float newRotation = rotation;
+ while (newRotation > 360) {
+ newRotation -= 360;
+ }
+ while (newRotation < 0) {
+ newRotation += 360;
+ }
+
+ this.rotation = newRotation;
+ if (markerViewManager != null) {
+ markerViewManager.animateRotationBy(this, newRotation);
+ }
+ }
+
+ /**
+ * Get the rotation value of the MarkerView.
+ *
+ * @return the rotation value.
+ */
+ public float getRotation() {
+ return rotation;
+ }
+
+ /**
+ * Get the alpha value of the MarkerView.
+ *
+ * @return the alpha value.
+ */
+ public float getAlpha() {
+ return alpha;
+ }
+
+ /**
+ * Set the alpha value of the MarkerView.
+ * <p>
+ * This will result in animating the alpha of the MarkerView using an alpha animator
+ * from current value to the provided parameter value.
+ * </p>
+ *
+ * @param alpha the alpha value to animate to.
+ */
+ public void setAlpha(@FloatRange(from = 0.0, to = 255.0) float alpha) {
+ this.alpha = alpha;
+ if (markerViewManager != null) {
+ markerViewManager.animateAlpha(this, alpha);
+ }
+ }
+
+ /**
+ * Set the icon of the MarkerView.
+ *
+ * @param icon the {@link Icon} to be used as Marker image.
+ */
+ @Override
+ public void setIcon(@Nullable Icon icon) {
+ if (icon != null) {
+ markerViewIcon = IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID, icon.getBitmap());
+ }
+ Icon transparentIcon = IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID,
+ IconFactory.ICON_MARKERVIEW_BITMAP);
+ if (markerViewManager != null) {
+ markerViewManager.updateIcon(this);
+ }
+ super.setIcon(transparentIcon);
+ }
+
+ /**
+ * Sets the location of the marker.
+ *
+ * @param position A {@link LatLng} defining the marker position.
+ */
+ @Override
+ public void setPosition(LatLng position) {
+ super.setPosition(position);
+ if (markerViewManager != null) {
+ markerViewManager.update();
+ }
+ }
+
+ /**
+ * Determine if the {@link MarkerView} is selected or not.
+ *
+ * @return True if the MarkerView's selected, else false.
+ */
+ public boolean isSelected() {
+ return selected;
+ }
+
+ /**
+ * For internal use only, use {@link MapboxMap#selectMarker(Marker)} instead.
+ */
+ void setSelected(boolean selected) {
+ this.selected = selected;
+ }
+
+ /**
+ * Get the icon of the MarkerView.
+ *
+ * @return the icon use as Marker image.
+ */
+ @Override
+ public Icon getIcon() {
+ return markerViewIcon;
+ }
+
+ /**
+ * Set the MapboxMap associated tot the MapView containing the MarkerView.
+ * <p>
+ * This method is used to instantiate the MarkerView and provide an instance of
+ * {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter}
+ * </p>
+ * <p>
+ * This method is used to notify that a MarkerView is no longer active by setting a null value.
+ * </p>
+ *
+ * @param mapboxMap the MapboxMap instances.
+ */
+ @Override
+ public void setMapboxMap(MapboxMap mapboxMap) {
+ super.setMapboxMap(mapboxMap);
+ if (mapboxMap != null) {
+ if (isFlat()) {
+ // initial tilt value if MapboxMap is started with a tilt attribute
+ tiltValue = (float) mapboxMap.getCameraPosition().tilt;
+ }
+
+ markerViewManager = mapboxMap.getMarkerViewManager();
+ }
+ }
+
+ /**
+ * Get the String representation of a MarkerView.
+ *
+ * @return the String representation.
+ */
+ @Override
+ public String toString() {
+ return "MarkerView [position[" + getPosition() + "]]";
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
index cd333268a1..ad221691b4 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
@@ -6,6 +6,7 @@ import android.graphics.RectF;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.v4.util.LongSparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -29,527 +30,627 @@ import java.util.Map;
* This class is responsible for managing a {@link MarkerView} item.
* </p>
*/
-public class MarkerViewManager {
-
- private Map<MarkerView, View> markerViewMap;
- private MapboxMap mapboxMap;
- private MapView mapView;
- private List<MapboxMap.MarkerViewAdapter> markerViewAdapters;
- private long viewMarkerBoundsUpdateTime;
- private MapboxMap.OnMarkerViewClickListener onMarkerViewClickListener;
- private ImageMarkerViewAdapter defaultMarkerViewAdapter;
-
- /**
- * Creates an instance of MarkerViewManager.
- *
- * @param mapboxMap the MapboxMap associated with the MarkerViewManager
- * @param mapView the MapView associated with the MarkerViewManager
- */
- public MarkerViewManager(@NonNull MapboxMap mapboxMap, @NonNull MapView mapView) {
- this.mapboxMap = mapboxMap;
- this.markerViewAdapters = new ArrayList<>();
- this.mapView = mapView;
- this.markerViewMap = new HashMap<>();
- this.defaultMarkerViewAdapter = new ImageMarkerViewAdapter(mapView.getContext());
- this.markerViewAdapters.add(defaultMarkerViewAdapter);
+public class MarkerViewManager implements MapView.OnMapChangedListener {
+
+ private final ViewGroup markerViewContainer;
+ private final Map<MarkerView, View> markerViewMap = new HashMap<>();
+ private final LongSparseArray<OnMarkerViewAddedListener> markerViewAddedListenerMap = new LongSparseArray<>();
+ private final List<MapboxMap.MarkerViewAdapter> markerViewAdapters = new ArrayList<>();
+
+ // TODO refactor MapboxMap out for Projection and Transform
+ // Requires removing MapboxMap from Annotations by using Peer model from #6912
+ private MapboxMap mapboxMap;
+
+ private boolean enabled;
+ private long updateTime;
+ private MapboxMap.OnMarkerViewClickListener onMarkerViewClickListener;
+ private boolean isWaitingForRenderInvoke;
+
+ /**
+ * Creates an instance of MarkerViewManager.
+ *
+ * @param container the ViewGroup associated with the MarkerViewManager
+ */
+ public MarkerViewManager(@NonNull ViewGroup container) {
+ this.markerViewContainer = container;
+ this.markerViewAdapters.add(new ImageMarkerViewAdapter(container.getContext()));
+ }
+
+ // TODO refactor MapboxMap out for Projection and Transform
+ // Requires removing MapboxMap from Annotations by using Peer model from #6912
+ public void bind(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ }
+
+ @Override
+ public void onMapChanged(@MapView.MapChange int change) {
+ if (isWaitingForRenderInvoke && change == MapView.DID_FINISH_RENDERING_FRAME_FULLY_RENDERED) {
+ isWaitingForRenderInvoke = false;
+ invalidateViewMarkersInVisibleRegion();
}
-
- /**
- * Animate a MarkerView to a given rotation.
- * <p>
- * The {@link MarkerView} will be rotated from its current rotation to the given rotation.
- * </p>
- *
- * @param marker the MarkerView to rotate
- * @param rotation the rotation value
- */
- public void animateRotation(@NonNull MarkerView marker, float rotation) {
- View convertView = markerViewMap.get(marker);
- if (convertView != null) {
- AnimatorUtils.rotate(convertView, rotation);
- }
+ }
+
+ /**
+ * Called to enable or disable MarkerView management.
+ *
+ * @param enabled true if management should be enabled
+ */
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ /**
+ * Called with true to wait for the next render invocation.
+ *
+ * @param waitingForRenderInvoke true if waiting for next render event
+ */
+ public void setWaitingForRenderInvoke(boolean waitingForRenderInvoke) {
+ isWaitingForRenderInvoke = waitingForRenderInvoke;
+ }
+
+ /**
+ * Animate a MarkerView to a given rotation.
+ * <p>
+ * The {@link MarkerView} will be rotated from its current rotation to the given rotation.
+ * </p>
+ *
+ * @param marker the MarkerView to rotate.
+ * @param rotation the rotation value.
+ */
+ public void animateRotation(@NonNull MarkerView marker, float rotation) {
+ View convertView = markerViewMap.get(marker);
+ if (convertView != null) {
+ AnimatorUtils.rotate(convertView, rotation);
}
-
- /**
- * Animate a MarkerView with a given rotation.
- *
- * @param marker the MarkerView to rotate by
- * @param rotation the rotation by value
- */
- public void animateRotationBy(@NonNull MarkerView marker, float rotation) {
- View convertView = markerViewMap.get(marker);
- if (convertView != null) {
- AnimatorUtils.rotateBy(convertView, rotation);
- }
+ }
+
+ /**
+ * Animate a MarkerView with a given rotation.
+ *
+ * @param marker the MarkerView to rotate by.
+ * @param rotation the rotation by value, limited to 0 - 360 degrees.
+ */
+ public void animateRotationBy(@NonNull MarkerView marker, float rotation) {
+ View convertView = markerViewMap.get(marker);
+ if (convertView != null) {
+ convertView.animate().cancel();
+ // calculate new direction
+ float diff = rotation - convertView.getRotation();
+ if (diff > 180.0f) {
+ diff -= 360.0f;
+ } else if (diff < -180.0f) {
+ diff += 360.f;
+ }
+ AnimatorUtils.rotateBy(convertView, diff);
}
-
- /**
- * Animate a MarkerView to a given alpha value.
- * <p>
- * The {@link MarkerView} will be transformed from its current alpha value to the given value.
- * </p>
- *
- * @param marker the MarkerView to change its alpha value
- * @param alpha the alpha value
- */
- public void animateAlpha(@NonNull MarkerView marker, float alpha) {
- View convertView = markerViewMap.get(marker);
- if (convertView != null) {
- AnimatorUtils.alpha(convertView, alpha);
- }
+ }
+
+ /**
+ * Animate a MarkerView to a given alpha value.
+ * <p>
+ * The {@link MarkerView} will be transformed from its current alpha value to the given value.
+ * </p>
+ *
+ * @param marker the MarkerView to change its alpha value.
+ * @param alpha the alpha value.
+ */
+ public void animateAlpha(@NonNull MarkerView marker, float alpha) {
+ View convertView = markerViewMap.get(marker);
+ if (convertView != null) {
+ AnimatorUtils.alpha(convertView, alpha);
}
-
- /**
- * Animate a MarkerVIew to be visible or invisible
- * <p>
- * The {@link MarkerView} will be made {@link View#VISIBLE} or {@link View#GONE}.
- * </p>
- *
- * @param marker the MarkerView to change its visibility
- * @param visible the flag indicating if MarkerView is visible
- */
- public void animateVisible(@NonNull MarkerView marker, boolean visible) {
- View convertView = markerViewMap.get(marker);
- if (convertView != null) {
- convertView.setVisibility(visible ? View.VISIBLE : View.GONE);
- }
+ }
+
+ /**
+ * Animate a MarkerVIew to be visible or invisible
+ * <p>
+ * The {@link MarkerView} will be made {@link View#VISIBLE} or {@link View#GONE}.
+ * </p>
+ *
+ * @param marker the MarkerView to change its visibility
+ * @param visible the flag indicating if MarkerView is visible
+ */
+ public void animateVisible(@NonNull MarkerView marker, boolean visible) {
+ View convertView = markerViewMap.get(marker);
+ if (convertView != null) {
+ convertView.setVisibility(visible ? View.VISIBLE : View.GONE);
}
-
- /**
- * Updates the position of MarkerViews currently found in the viewport.
- * <p>
- * The collection of {@link MarkerView} will be iterated and each item position will be updated.
- * If an item is View state is not visible and its related flag is set to visible,
- * The {@link MarkerView} will be animated to visible using alpha animation.
- * </p>
- */
- public void update() {
- for (final MarkerView marker : markerViewMap.keySet()) {
- final View convertView = markerViewMap.get(marker);
- if (convertView != null) {
- PointF point = mapboxMap.getProjection().toScreenLocation(marker.getPosition());
- if (marker.getOffsetX() == MapboxConstants.UNMEASURED) {
- // ensure view is measured first
- if (marker.getWidth() == 0) {
- convertView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
- if (convertView.getMeasuredWidth() != 0) {
- marker.setWidth(convertView.getMeasuredWidth());
- marker.setHeight(convertView.getMeasuredHeight());
- }
- }
- }
- if (marker.getWidth() != 0) {
- int x = (int) (marker.getAnchorU() * marker.getWidth());
- int y = (int) (marker.getAnchorV() * marker.getHeight());
- marker.setOffset(x, y);
- }
-
- convertView.setX(point.x - marker.getOffsetX());
- convertView.setY(point.y - marker.getOffsetY());
-
- // animate visibility
- if (marker.isVisible() && convertView.getVisibility() == View.GONE) {
- animateVisible(marker, true);
- }
+ }
+
+ /**
+ * Updates the position of MarkerViews currently found in the viewport.
+ * <p>
+ * The collection of {@link MarkerView} will be iterated and each item position will be updated.
+ * If an item is View state is not visible and its related flag is set to visible, the
+ * {@link MarkerView} will be animated to visible using alpha animation.
+ * </p>
+ */
+ public void updateMarkerViewsPosition() {
+ for (final MarkerView marker : markerViewMap.keySet()) {
+ final View convertView = markerViewMap.get(marker);
+ if (convertView != null) {
+ PointF point = mapboxMap.getProjection().toScreenLocation(marker.getPosition());
+ if (marker.getOffsetX() == MapboxConstants.UNMEASURED) {
+ // ensure view is measured first
+ if (marker.getWidth() == 0) {
+ convertView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+ if (convertView.getMeasuredWidth() != 0) {
+ marker.setWidth(convertView.getMeasuredWidth());
+ marker.setHeight(convertView.getMeasuredHeight());
}
+ }
+ }
+ if (marker.getWidth() != 0) {
+ int x = (int) (marker.getAnchorU() * marker.getWidth());
+ int y = (int) (marker.getAnchorV() * marker.getHeight());
+ marker.setOffset(x, y);
}
- }
- /**
- * Set tilt on every non flat MarkerView currently shown in the Viewport.
- *
- * @param tilt the tilt value
- */
- public void setTilt(float tilt) {
- View convertView;
- for (MarkerView markerView : markerViewMap.keySet()) {
- if (markerView.isFlat()) {
- convertView = markerViewMap.get(markerView);
- if (convertView != null) {
- markerView.setTilt(tilt);
- convertView.setRotationX(tilt);
- }
- }
+ convertView.setX(point.x - marker.getOffsetX());
+ convertView.setY(point.y - marker.getOffsetY());
+
+ // animate visibility
+ if (marker.isVisible() && convertView.getVisibility() == View.GONE) {
+ animateVisible(marker, true);
}
+ }
}
-
- /**
- * Update and invalidate the MarkerView icon.
- *
- * @param markerView the marker view to updates
- */
- public void updateIcon(@NonNull MarkerView markerView) {
- View convertView = markerViewMap.get(markerView);
- if (convertView != null && convertView instanceof ImageView) {
- ((ImageView) convertView).setImageBitmap(markerView.getIcon().getBitmap());
+ }
+
+ /**
+ * Set tilt on every non flat MarkerView currently shown in the Viewport.
+ *
+ * @param tilt the tilt value.
+ */
+ public void setTilt(float tilt) {
+ View convertView;
+ for (MarkerView markerView : markerViewMap.keySet()) {
+ if (markerView.isFlat()) {
+ convertView = markerViewMap.get(markerView);
+ if (convertView != null) {
+ markerView.setTilt(tilt);
+ convertView.setRotationX(tilt);
}
+ }
}
-
- /**
- * Animate a MarkerView to a deselected state.
- * <p>
- * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onDeselect(MarkerView, View)} will be called to execute an animation.
- * </p>
- *
- * @param marker the MarkerView to deselect
- */
- public void deselect(@NonNull MarkerView marker) {
- deselect(marker, true);
+ }
+
+ /**
+ * Update and invalidate the MarkerView icon.
+ *
+ * @param markerView the marker view to updates.
+ */
+ public void updateIcon(@NonNull MarkerView markerView) {
+ View convertView = markerViewMap.get(markerView);
+ if (convertView != null && convertView instanceof ImageView) {
+ ((ImageView) convertView).setImageBitmap(markerView.getIcon().getBitmap());
}
-
- /**
- * Animate a MarkerView to a deselected state.
- * <p>
- * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onDeselect(MarkerView, View)} will be called to execute an animation.
- * </p>
- *
- * @param marker the MarkerView to deselect
- * @param callbackToMap indicates if deselect marker must be called on MapboxMap
- */
- public void deselect(@NonNull MarkerView marker, boolean callbackToMap) {
- final View convertView = markerViewMap.get(marker);
- if (convertView != null) {
- for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
- if (adapter.getMarkerClass().equals(marker.getClass())) {
- adapter.onDeselect(marker, convertView);
- }
- }
- if (callbackToMap) {
- mapboxMap.deselectMarker(marker);
- }
- marker.setSelected(false);
+ }
+
+ /**
+ * Animate a MarkerView to a deselected state.
+ * <p>
+ * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onDeselect(MarkerView, View)}
+ * will be called to execute an animation.
+ * </p>
+ *
+ * @param marker the MarkerView to deselect.
+ */
+ public void deselect(@NonNull MarkerView marker) {
+ deselect(marker, true);
+ }
+
+ /**
+ * Animate a MarkerView to a deselected state.
+ * <p>
+ * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onDeselect(MarkerView, View)}
+ * will be called to execute an animation.
+ * </p>
+ *
+ * @param marker the MarkerView to deselect.
+ * @param callbackToMap indicates if deselect marker must be called on MapboxMap.
+ */
+ public void deselect(@NonNull MarkerView marker, boolean callbackToMap) {
+ final View convertView = markerViewMap.get(marker);
+ if (convertView != null) {
+ for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
+ if (adapter.getMarkerClass().equals(marker.getClass())) {
+ adapter.onDeselect(marker, convertView);
}
+ }
}
-
- /**
- * Animate a MarkerView to a selected state.
- *
- * @param marker the MarkerView object to select
- */
- public void select(@NonNull MarkerView marker) {
- select(marker, true);
+ if (callbackToMap) {
+ mapboxMap.deselectMarker(marker);
}
-
- /**
- * Animate a MarkerView to a selected state.
- *
- * @param marker the MarkerView object to select
- * @param callbackToMap indicates if select marker must be called on MapboxMap
- */
- public void select(@NonNull MarkerView marker, boolean callbackToMap) {
- final View convertView = markerViewMap.get(marker);
- for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
- if (adapter.getMarkerClass().equals(marker.getClass())) {
- select(marker, convertView, adapter, callbackToMap);
- }
+ marker.setSelected(false);
+ }
+
+ /**
+ * Animate a MarkerView to a selected state.
+ *
+ * @param marker the MarkerView object to select.
+ */
+ public void select(@NonNull MarkerView marker) {
+ select(marker, true);
+ }
+
+ /**
+ * Animate a MarkerView to a selected state.
+ *
+ * @param marker the MarkerView object to select.
+ * @param callbackToMap indicates if select marker must be called on {@link MapboxMap}.
+ */
+ public void select(@NonNull MarkerView marker, boolean callbackToMap) {
+ final View convertView = markerViewMap.get(marker);
+ for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
+ if (adapter.getMarkerClass().equals(marker.getClass())) {
+ select(marker, convertView, adapter, callbackToMap);
+ }
+ }
+ }
+
+ /**
+ * Animate a MarkerView to a selected state.
+ * <p>
+ * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onSelect(MarkerView, View, boolean)}
+ * will be called to execute an animation.
+ * </p>
+ *
+ * @param marker the MarkerView object to select.
+ * @param convertView the View presentation of the MarkerView.
+ * @param adapter the adapter used to adapt the marker to the convertView.
+ */
+ public void select(@NonNull MarkerView marker, View convertView, MapboxMap.MarkerViewAdapter adapter) {
+ select(marker, convertView, adapter, true);
+ }
+
+
+ /**
+ * Animate a MarkerView to a selected state.
+ * <p>
+ * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onSelect(MarkerView, View, boolean)}
+ * will be called to execute an animation.
+ * </p>
+ *
+ * @param marker the MarkerView object to select.
+ * @param convertView the View presentation of the MarkerView.
+ * @param adapter the adapter used to adapt the marker to the convertView.
+ * @param callbackToMap indicates if select marker must be called on MapboxMap.
+ */
+ public void select(@NonNull MarkerView marker, View convertView, MapboxMap.MarkerViewAdapter adapter,
+ boolean callbackToMap) {
+ if (convertView != null) {
+ if (adapter.onSelect(marker, convertView, false)) {
+ if (callbackToMap) {
+ mapboxMap.selectMarker(marker);
}
+ }
+ marker.setSelected(true);
+ convertView.bringToFront();
}
-
- /**
- * Animate a MarkerView to a selected state.
- * <p>
- * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onSelect(MarkerView, View, boolean)} will be called to execute an animation.
- * </p>
- *
- * @param marker the MarkerView object to select
- * @param convertView the View presentation of the MarkerView
- * @param adapter the adapter used to adapt the marker to the convertView
- */
- public void select(@NonNull MarkerView marker, View convertView, MapboxMap.MarkerViewAdapter adapter) {
- select(marker, convertView, adapter, true);
+ }
+
+ /**
+ * Get view representation from a MarkerView. If marker is not found in current viewport,
+ * {@code null} is returned.
+ *
+ * @param marker the marker to get the view.
+ * @return the Android SDK View object.
+ */
+ @Nullable
+ public View getView(MarkerView marker) {
+ return markerViewMap.get(marker);
+ }
+
+ /**
+ * Get the view adapter for a marker.
+ *
+ * @param markerView the marker to get the view adapter.
+ * @return the MarkerView adapter.
+ */
+ @Nullable
+ public MapboxMap.MarkerViewAdapter getViewAdapter(MarkerView markerView) {
+ MapboxMap.MarkerViewAdapter adapter = null;
+ for (MapboxMap.MarkerViewAdapter a : markerViewAdapters) {
+ if (a.getMarkerClass().equals(markerView.getClass())) {
+ adapter = a;
+ }
}
-
-
- /**
- * Animate a MarkerView to a selected state.
- * <p>
- * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onSelect(MarkerView, View, boolean)} will be called to execute an animation.
- * </p>
- *
- * @param marker the MarkerView object to select
- * @param convertView the View presentation of the MarkerView
- * @param adapter the adapter used to adapt the marker to the convertView
- * @param callbackToMap indicates if select marker must be called on MapboxMap
- */
- public void select(@NonNull MarkerView marker, View convertView, MapboxMap.MarkerViewAdapter adapter, boolean callbackToMap) {
- if (convertView != null) {
- if (adapter.onSelect(marker, convertView, false)) {
- if (callbackToMap) {
- mapboxMap.selectMarker(marker);
- }
- }
- marker.setSelected(true);
- convertView.bringToFront();
+ return adapter;
+ }
+
+ /**
+ * Remove a MarkerView from a map.
+ * <p>
+ * The {@link MarkerView} will be removed using an alpha animation and related {@link View}
+ * will be released to the android.support.v4.util.Pools.SimplePool from the related
+ * {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter}. It's possible to remove
+ * the {@link MarkerView} from the underlying collection if needed.
+ * </p>
+ *
+ * @param marker the MarkerView to remove.
+ */
+ public void removeMarkerView(MarkerView marker) {
+ final View viewHolder = markerViewMap.get(marker);
+ if (viewHolder != null && marker != null) {
+ for (final MapboxMap.MarkerViewAdapter<?> adapter : markerViewAdapters) {
+ if (adapter.getMarkerClass().equals(marker.getClass())) {
+ if (adapter.prepareViewForReuse(marker, viewHolder)) {
+ // reset offset for reuse
+ marker.setOffset(MapboxConstants.UNMEASURED, MapboxConstants.UNMEASURED);
+ adapter.releaseView(viewHolder);
+ }
}
+ }
}
-
- /**
- * Get view representation from a MarkerView.
- * <p>
- * If marker is not found in current viewport, null is returned.
- * </p>
- *
- * @param marker the marker to get the view for
- * @return the android SDK View object
- */
- @Nullable
- public View getView(MarkerView marker) {
- return markerViewMap.get(marker);
+ marker.setMapboxMap(null);
+ markerViewMap.remove(marker);
+ }
+
+ /**
+ * Add a MarkerViewAdapter to the MarkerViewManager.
+ * <p>
+ * The provided MarkerViewAdapter must supply a generic subclass of MarkerView.
+ * </p>
+ *
+ * @param markerViewAdapter the MarkerViewAdapter to add.
+ */
+ public void addMarkerViewAdapter(MapboxMap.MarkerViewAdapter markerViewAdapter) {
+ if (markerViewAdapter.getMarkerClass().equals(MarkerView.class)) {
+ throw new RuntimeException("Providing a custom MarkerViewAdapter requires subclassing MarkerView");
}
- @Nullable
- public MapboxMap.MarkerViewAdapter getViewAdapter(MarkerView markerView) {
- MapboxMap.MarkerViewAdapter adapter = null;
- for (MapboxMap.MarkerViewAdapter a : markerViewAdapters) {
- if (a.getMarkerClass().equals(markerView.getClass())) {
- adapter = a;
- }
+ if (!markerViewAdapters.contains(markerViewAdapter)) {
+ markerViewAdapters.add(markerViewAdapter);
+ invalidateViewMarkersInVisibleRegion();
+ }
+ }
+
+ /**
+ * Get all MarkerViewAdapters associated with this MarkerViewManager.
+ *
+ * @return a List of MarkerViewAdapters.
+ */
+ public List<MapboxMap.MarkerViewAdapter> getMarkerViewAdapters() {
+ return markerViewAdapters;
+ }
+
+ /**
+ * Register a callback to be invoked when this view is clicked.
+ *
+ * @param listener the callback to be invoked.
+ */
+ public void setOnMarkerViewClickListener(@Nullable MapboxMap.OnMarkerViewClickListener listener) {
+ onMarkerViewClickListener = listener;
+ }
+
+ /**
+ * Schedule that ViewMarkers found in the viewport are invalidated.
+ * <p>
+ * This method is rate limited, and {@link #invalidateViewMarkersInVisibleRegion} will only be called
+ * once each 250 ms.
+ * </p>
+ */
+ public void update() {
+ if (enabled) {
+ long currentTime = SystemClock.elapsedRealtime();
+ if (currentTime < updateTime) {
+ updateMarkerViewsPosition();
+ return;
+ }
+ invalidateViewMarkersInVisibleRegion();
+ updateTime = currentTime + 250;
+ }
+ }
+
+ /**
+ * Invalidate the ViewMarkers found in the viewport.
+ * <p>
+ * This method will remove any markers that aren't in the viewport anymore and will add new
+ * ones for each found Marker in the changed viewport.
+ * </p>
+ */
+ public void invalidateViewMarkersInVisibleRegion() {
+ RectF mapViewRect = new RectF(0, 0, markerViewContainer.getWidth(), markerViewContainer.getHeight());
+ List<MarkerView> markers = mapboxMap.getMarkerViewsInRect(mapViewRect);
+ View convertView;
+
+ // remove old markers
+ Iterator<MarkerView> iterator = markerViewMap.keySet().iterator();
+ while (iterator.hasNext()) {
+ MarkerView marker = iterator.next();
+ if (!markers.contains(marker)) {
+ // remove marker
+ convertView = markerViewMap.get(marker);
+ for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
+ if (adapter.getMarkerClass().equals(marker.getClass())) {
+ adapter.prepareViewForReuse(marker, convertView);
+ adapter.releaseView(convertView);
+ marker.setMapboxMap(null);
+ iterator.remove();
+ }
}
- return adapter;
+ }
}
- /**
- * Remove a MarkerView from a map.
- * <p>
- * The {@link MarkerView} will be removed using an alpha animation and related {@link View}
- * will be released to the android.support.v4.util.Pools.SimplePool from the related
- * {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter}. It's possible to remove
- * the {@link MarkerView} from the underlying collection if needed.
- * </p>
- *
- * @param marker the MarkerView to remove
- */
- public void removeMarkerView(MarkerView marker) {
- final View viewHolder = markerViewMap.get(marker);
- if (viewHolder != null && marker != null) {
- for (final MapboxMap.MarkerViewAdapter<?> adapter : markerViewAdapters) {
- if (adapter.getMarkerClass().equals(marker.getClass())) {
- if (adapter.prepareViewForReuse(marker, viewHolder)) {
- // reset offset for reuse
- marker.setOffset(MapboxConstants.UNMEASURED, MapboxConstants.UNMEASURED);
- adapter.releaseView(viewHolder);
- }
+ // introduce new markers
+ for (final MarkerView marker : markers) {
+ if (!markerViewMap.containsKey(marker)) {
+ for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
+ if (adapter.getMarkerClass().equals(marker.getClass())) {
+
+ // Inflate View
+ convertView = (View) adapter.getViewReusePool().acquire();
+ final View adaptedView = adapter.getView(marker, convertView, markerViewContainer);
+ if (adaptedView != null) {
+ adaptedView.setRotationX(marker.getTilt());
+ adaptedView.setRotation(marker.getRotation());
+ adaptedView.setAlpha(marker.getAlpha());
+ adaptedView.setVisibility(View.GONE);
+
+ if (mapboxMap.getSelectedMarkers().contains(marker)) {
+ // if a marker to be shown was selected
+ // replay that animation with duration 0
+ if (adapter.onSelect(marker, adaptedView, true)) {
+ mapboxMap.selectMarker(marker);
}
+ }
+
+ marker.setMapboxMap(mapboxMap);
+ markerViewMap.put(marker, adaptedView);
+ if (convertView == null) {
+ adaptedView.setVisibility(View.GONE);
+ markerViewContainer.addView(adaptedView);
+ }
}
- }
- marker.setMapboxMap(null);
- markerViewMap.remove(marker);
- }
-
- /**
- * Add a MarkerViewAdapter to the MarkerViewManager.
- * <p>
- * The provided MarkerViewAdapter must use supply a generic subclass of MarkerView.
- * </p>
- *
- * @param markerViewAdapter the MarkerViewAdapter to add
- */
- public void addMarkerViewAdapter(MapboxMap.MarkerViewAdapter markerViewAdapter) {
- if (markerViewAdapter.getMarkerClass().equals(MarkerView.class)) {
- throw new RuntimeException("Providing a custom MarkerViewAdapter requires subclassing MarkerView");
- }
- if (!markerViewAdapters.contains(markerViewAdapter)) {
- markerViewAdapters.add(markerViewAdapter);
- invalidateViewMarkersInVisibleRegion();
+ // notify listener is marker view is rendered
+ OnMarkerViewAddedListener onViewAddedListener = markerViewAddedListenerMap.get(marker.getId());
+ if (onViewAddedListener != null) {
+ onViewAddedListener.onViewAdded(marker);
+ markerViewAddedListenerMap.remove(marker.getId());
+ }
+ }
}
+ }
}
- /**
- * Get all MarkerViewAdapters associated with this MarkerViewManager.
- *
- * @return a List of MarkerViewAdapters
- */
- public List<MapboxMap.MarkerViewAdapter> getMarkerViewAdapters() {
- return markerViewAdapters;
+ // clear map, don't keep references to MarkerView listeners that are not found in the bounds of the map.
+ markerViewAddedListenerMap.clear();
+
+ // trigger update to make newly added ViewMarker visible,
+ // these would only be updated when the map is moved.
+ updateMarkerViewsPosition();
+ }
+
+ /**
+ * When the provided {@link MarkerView} is clicked on by a user, we check if a custom click
+ * event has been created and if not, display a {@link InfoWindow}.
+ *
+ * @param markerView that the click event occurred.
+ */
+ public boolean onClickMarkerView(MarkerView markerView) {
+ boolean clickHandled = false;
+
+ MapboxMap.MarkerViewAdapter adapter = getViewAdapter(markerView);
+ View view = getView(markerView);
+ if (adapter == null || view == null) {
+ // not a valid state
+ return true;
}
- /**
- * Register a callback to be invoked when this view is clicked.
- *
- * @param listener the callback to be invoked
- */
- public void setOnMarkerViewClickListener(@Nullable MapboxMap.OnMarkerViewClickListener listener) {
- onMarkerViewClickListener = listener;
+ if (onMarkerViewClickListener != null) {
+ clickHandled = onMarkerViewClickListener.onMarkerClick(markerView, view, adapter);
}
- /**
- * Schedule that ViewMarkers found in the viewport are invalidated.
- * <p>
- * This method is rate limited, and {@link #invalidateViewMarkersInVisibleRegion} will only be called
- * once each 250 ms.
- * </p>
- */
- public void scheduleViewMarkerInvalidation() {
- if (!markerViewAdapters.isEmpty()) {
- long currentTime = SystemClock.elapsedRealtime();
- if (currentTime < viewMarkerBoundsUpdateTime) {
- return;
- }
- invalidateViewMarkersInVisibleRegion();
- viewMarkerBoundsUpdateTime = currentTime + 250;
- }
+ if (!clickHandled) {
+ ensureInfoWindowOffset(markerView);
+ select(markerView, view, adapter);
}
- /**
- * Invalidate the ViewMarkers found in the viewport.
- * <p>
- * This method will remove any markers that aren't in the viewport any more and will add new
- * ones for each found Marker in the changed viewport.
- * </p>
- */
- public void invalidateViewMarkersInVisibleRegion() {
- RectF mapViewRect = new RectF(0, 0, mapView.getWidth(), mapView.getHeight());
- List<MarkerView> markers = mapView.getMarkerViewsInRect(mapViewRect);
- View convertView;
-
- // remove old markers
- Iterator<MarkerView> iterator = markerViewMap.keySet().iterator();
- while (iterator.hasNext()) {
- MarkerView marker = iterator.next();
- if (!markers.contains(marker)) {
- // remove marker
- convertView = markerViewMap.get(marker);
- for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
- if (adapter.getMarkerClass().equals(marker.getClass())) {
- adapter.prepareViewForReuse(marker, convertView);
- adapter.releaseView(convertView);
- marker.setMapboxMap(null);
- iterator.remove();
- }
- }
- }
+ return clickHandled;
+ }
+
+ /**
+ * Handles the {@link MarkerView}'s info window offset.
+ *
+ * @param marker that we are ensuring info window offset.
+ */
+ public void ensureInfoWindowOffset(MarkerView marker) {
+ View view = null;
+ if (markerViewMap.containsKey(marker)) {
+ view = markerViewMap.get(marker);
+ } else {
+ for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
+ if (adapter.getMarkerClass().equals(marker.getClass())) {
+ View convertView = (View) adapter.getViewReusePool().acquire();
+ view = adapter.getView(marker, convertView, markerViewContainer);
+ break;
}
+ }
+ }
- // introduce new markers
- for (final MarkerView marker : markers) {
- if (!markerViewMap.containsKey(marker)) {
- for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
- if (adapter.getMarkerClass().equals(marker.getClass())) {
-
- // Inflate View
- convertView = (View) adapter.getViewReusePool().acquire();
- final View adaptedView = adapter.getView(marker, convertView, mapView);
- if (adaptedView != null) {
- adaptedView.setRotationX(marker.getTilt());
- adaptedView.setRotation(marker.getRotation());
- adaptedView.setAlpha(marker.getAlpha());
- adaptedView.setVisibility(View.GONE);
-
- if (mapboxMap.getSelectedMarkers().contains(marker)) {
- // if a marker to be shown was selected
- // replay that animation with duration 0
- if (adapter.onSelect(marker, adaptedView, true)) {
- mapboxMap.selectMarker(marker);
- }
- }
-
- marker.setMapboxMap(mapboxMap);
- markerViewMap.put(marker, adaptedView);
- if (convertView == null) {
- adaptedView.setVisibility(View.GONE);
- mapView.getMarkerViewContainer().addView(adaptedView);
- }
- }
- }
- }
- }
+ if (view != null) {
+ if (marker.getWidth() == 0) {
+ if (view.getMeasuredWidth() == 0) {
+ //Ensure the marker's view is measured first
+ view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
}
- // trigger update to make newly added ViewMarker visible,
- // these would only be updated when the map is moved.
- update();
+ marker.setWidth(view.getMeasuredWidth());
+ marker.setHeight(view.getMeasuredHeight());
+ }
+
+ // update position on map
+ if (marker.getOffsetX() == MapboxConstants.UNMEASURED) {
+ int x = (int) (marker.getAnchorU() * marker.getWidth());
+ int y = (int) (marker.getAnchorV() * marker.getHeight());
+ marker.setOffset(x, y);
+ }
+
+ // InfoWindow offset
+ int infoWindowOffsetX = (int) ((view.getMeasuredWidth() * marker.getInfoWindowAnchorU()) - marker.getOffsetX());
+ int infoWindowOffsetY = (int) ((view.getMeasuredHeight() * marker.getInfoWindowAnchorV()) - marker.getOffsetY());
+ marker.setTopOffsetPixels(infoWindowOffsetY);
+ marker.setRightOffsetPixels(infoWindowOffsetX);
}
+ }
- public void onClickMarkerView(MarkerView markerView) {
- boolean clickHandled = false;
+ public ViewGroup getMarkerViewContainer() {
+ return markerViewContainer;
+ }
- MapboxMap.MarkerViewAdapter adapter = getViewAdapter(markerView);
- View view = getView(markerView);
- if (adapter == null || view == null) {
- // not a valid state
- return;
- }
+ public void addOnMarkerViewAddedListener(MarkerView markerView, OnMarkerViewAddedListener onMarkerViewAddedListener) {
+ markerViewAddedListenerMap.put(markerView.getId(), onMarkerViewAddedListener);
+ }
- if (onMarkerViewClickListener != null) {
- clickHandled = onMarkerViewClickListener.onMarkerClick(markerView, view, adapter);
- }
+ /**
+ * Default MarkerViewAdapter used for base class of {@link MarkerView} to adapt a MarkerView to
+ * an ImageView.
+ */
+ private static class ImageMarkerViewAdapter extends MapboxMap.MarkerViewAdapter<MarkerView> {
- if (!clickHandled) {
- ensureInfoWindowOffset(markerView);
- select(markerView, view, adapter);
- }
- }
-
- //TODO: This whole method is a stopgap for: https://github.com/mapbox/mapbox-gl-native/issues/5384
- public void ensureInfoWindowOffset(MarkerView marker) {
- View view = null;
- if (markerViewMap.containsKey(marker)) {
- view = markerViewMap.get(marker);
- } else {
- for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
- if (adapter.getMarkerClass().equals(marker.getClass())) {
- View convertView = (View) adapter.getViewReusePool().acquire();
- view = adapter.getView(marker, convertView, mapView);
- break;
- }
- }
- }
+ private LayoutInflater inflater;
- if (view != null) {
- if (marker.getWidth() == 0) {
- if(view.getMeasuredWidth()==0) {
- //Ensure the marker's view is measured first
- view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
- }
- marker.setWidth(view.getMeasuredWidth());
- marker.setHeight(view.getMeasuredHeight());
- }
+ ImageMarkerViewAdapter(Context context) {
+ super(context);
+ inflater = LayoutInflater.from(context);
+ }
- // update position on map
- if (marker.getOffsetX() == MapboxConstants.UNMEASURED) {
- int x = (int) (marker.getAnchorU() * marker.getWidth());
- int y = (int) (marker.getAnchorV() * marker.getHeight());
- marker.setOffset(x, y);
- }
+ @Nullable
+ @Override
+ public View getView(@NonNull MarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
+ ViewHolder viewHolder;
+ if (convertView == null) {
+ viewHolder = new ViewHolder();
+ convertView = inflater.inflate(R.layout.mapbox_view_image_marker, parent, false);
+ viewHolder.imageView = (ImageView) convertView.findViewById(R.id.image);
+ convertView.setTag(viewHolder);
+ } else {
+ viewHolder = (ViewHolder) convertView.getTag();
+ }
+ viewHolder.imageView.setImageBitmap(marker.getIcon().getBitmap());
+ return convertView;
+ }
- // InfoWindow offset
- int infoWindowOffsetX = (int) ((view.getMeasuredWidth() * marker.getInfoWindowAnchorU()) - marker.getOffsetX());
- int infoWindowOffsetY = (int) ((view.getMeasuredHeight() * marker.getInfoWindowAnchorV()) - marker.getOffsetY());
- marker.setTopOffsetPixels(infoWindowOffsetY);
- marker.setRightOffsetPixels(infoWindowOffsetX);
- }
+ private static class ViewHolder {
+ ImageView imageView;
}
+ }
+
+ /**
+ * Interface definition invoked when the View of a MarkerView has been added to the map.
+ * <p>
+ * {@link MapboxMap#addMarker(BaseMarkerOptions)}
+ * and only when the related MarkerView is found in the viewport of the map.
+ * </p>
+ */
+ public interface OnMarkerViewAddedListener {
/**
- * Default MarkerViewAdapter used for base class of MarkerView to adapt a MarkerView to an ImageView
+ * Invoked when the View of a MarkerView has been added to the Map.
+ *
+ * @param markerView The MarkerView the View was added for
*/
- public static class ImageMarkerViewAdapter extends MapboxMap.MarkerViewAdapter<MarkerView> {
-
- private LayoutInflater inflater;
-
- public ImageMarkerViewAdapter(Context context) {
- super(context);
- inflater = LayoutInflater.from(context);
- }
-
- @Nullable
- @Override
- public View getView(@NonNull MarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
- ViewHolder viewHolder;
- if (convertView == null) {
- viewHolder = new ViewHolder();
- convertView = inflater.inflate(R.layout.view_image_marker, parent, false);
- viewHolder.imageView = (ImageView) convertView.findViewById(R.id.image);
- convertView.setTag(viewHolder);
- } else {
- viewHolder = (ViewHolder) convertView.getTag();
- }
- viewHolder.imageView.setImageBitmap(marker.getIcon().getBitmap());
- return convertView;
- }
-
- private static class ViewHolder {
- ImageView imageView;
- }
- }
+ void onViewAdded(@NonNull MarkerView markerView);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java
index 86ad873347..2d829537fc 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java
@@ -10,108 +10,155 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
/**
* builder class for composing MarkerView objects.
* <p>
- * Do not extend this class directly but extend BaseMarkerViewOptions instead.
+ * Do not extend this class directly but extend {@link BaseMarkerViewOptions} instead.
* </p>
*/
public class MarkerViewOptions extends BaseMarkerViewOptions<MarkerView, MarkerViewOptions> {
- private MarkerView marker;
+ private MarkerView marker;
- public MarkerViewOptions() {
- marker = new MarkerView();
- }
+ /**
+ * Defines default options for a MarkerView. Extend {@link BaseMarkerViewOptions} if you need
+ * more customization.
+ */
+ public MarkerViewOptions() {
+ marker = new MarkerView();
+ }
- protected MarkerViewOptions(Parcel in) {
- marker = new MarkerView();
- position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
- snippet(in.readString());
- title(in.readString());
- flat(in.readByte() != 0);
- anchor(in.readFloat(), in.readFloat());
- infoWindowAnchor(in.readFloat(), in.readFloat());
- rotation(in.readFloat());
- visible(in.readByte() != 0);
- alpha(in.readFloat());
- if (in.readByte() != 0) {
- // this means we have an icon
- String iconId = in.readString();
- Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
- Icon icon = new Icon(iconId, iconBitmap);
- icon(icon);
- }
+ protected MarkerViewOptions(Parcel in) {
+ marker = new MarkerView();
+ position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
+ snippet(in.readString());
+ title(in.readString());
+ flat(in.readByte() != 0);
+ anchor(in.readFloat(), in.readFloat());
+ infoWindowAnchor(in.readFloat(), in.readFloat());
+ rotation(in.readFloat());
+ visible(in.readByte() != 0);
+ alpha(in.readFloat());
+ if (in.readByte() != 0) {
+ // this means we have an icon
+ String iconId = in.readString();
+ Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
+ Icon icon = new Icon(iconId, iconBitmap);
+ icon(icon);
}
+ }
- @Override
- public MarkerViewOptions getThis() {
- return this;
- }
+ /**
+ * Get the instance of the object for which this method was called.
+ *
+ * @return the object for which this method was called.
+ */
+ @Override
+ public MarkerViewOptions getThis() {
+ return this;
+ }
- @Override
- public int describeContents() {
- return 0;
- }
+ /**
+ * Describe the kinds of special objects contained in this Parcelable's
+ * marshalled representation.
+ *
+ * @return integer 0.
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(getPosition(), flags);
- out.writeString(getSnippet());
- out.writeString(getTitle());
- out.writeByte((byte) (isFlat() ? 1 : 0));
- out.writeFloat(getAnchorU());
- out.writeFloat(getAnchorV());
- out.writeFloat(getInfoWindowAnchorU());
- out.writeFloat(getInfoWindowAnchorV());
- out.writeFloat(getRotation());
- out.writeByte((byte) (isVisible() ? 1 : 0));
- out.writeFloat(alpha);
- Icon icon = getIcon();
- out.writeByte((byte) (icon != null ? 1 : 0));
- if (icon != null) {
- out.writeString(getIcon().getId());
- out.writeParcelable(getIcon().getBitmap(), flags);
- }
+ /**
+ * Flatten this object in to a Parcel.
+ *
+ * @param out The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written. May be 0 or
+ * {@link #PARCELABLE_WRITE_RETURN_VALUE}.
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(getPosition(), flags);
+ out.writeString(getSnippet());
+ out.writeString(getTitle());
+ out.writeByte((byte) (isFlat() ? 1 : 0));
+ out.writeFloat(getAnchorU());
+ out.writeFloat(getAnchorV());
+ out.writeFloat(getInfoWindowAnchorU());
+ out.writeFloat(getInfoWindowAnchorV());
+ out.writeFloat(getRotation());
+ out.writeByte((byte) (isVisible() ? 1 : 0));
+ out.writeFloat(alpha);
+ Icon icon = getIcon();
+ out.writeByte((byte) (icon != null ? 1 : 0));
+ if (icon != null) {
+ out.writeString(getIcon().getId());
+ out.writeParcelable(getIcon().getBitmap(), flags);
}
+ }
- @Override
- public MarkerView getMarker() {
- if (position == null) {
- throw new InvalidMarkerPositionException();
- }
-
- marker.setPosition(position);
- marker.setSnippet(snippet);
- marker.setTitle(title);
- marker.setIcon(icon);
- marker.setFlat(flat);
- marker.setAnchor(anchorU, anchorV);
- marker.setInfoWindowAnchor(infoWindowAnchorU, infoWindowAnchorV);
- marker.setRotation(rotation);
- marker.setVisible(visible);
- marker.setAlpha(alpha);
- return marker;
+ /**
+ * Get the {@link MarkerView}.
+ *
+ * @return {@link MarkerView}.
+ */
+ @Override
+ public MarkerView getMarker() {
+ if (position == null) {
+ throw new InvalidMarkerPositionException();
}
- public static final Parcelable.Creator<MarkerViewOptions> CREATOR
- = new Parcelable.Creator<MarkerViewOptions>() {
- public MarkerViewOptions createFromParcel(Parcel in) {
- return new MarkerViewOptions(in);
- }
+ marker.setPosition(position);
+ marker.setSnippet(snippet);
+ marker.setTitle(title);
+ marker.setIcon(icon);
+ marker.setFlat(flat);
+ marker.setAnchor(anchorU, anchorV);
+ marker.setInfoWindowAnchor(infoWindowAnchorU, infoWindowAnchorV);
+ marker.setRotation(rotation);
+ marker.setVisible(visible);
+ marker.setAlpha(alpha);
+ return marker;
+ }
- public MarkerViewOptions[] newArray(int size) {
- return new MarkerViewOptions[size];
- }
+ public static final Parcelable.Creator<MarkerViewOptions> CREATOR =
+ new Parcelable.Creator<MarkerViewOptions>() {
+ public MarkerViewOptions createFromParcel(Parcel in) {
+ return new MarkerViewOptions(in);
+ }
+
+ public MarkerViewOptions[] newArray(int size) {
+ return new MarkerViewOptions[size];
+ }
};
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- MarkerViewOptions that = (MarkerViewOptions) o;
- return marker != null ? marker.equals(that.marker) : that.marker == null;
+ /**
+ * Compares this {@link MarkerViewOptions} object with another {@link MarkerViewOptions} and
+ * determines if they match.
+ *
+ * @param object Another {@link MarkerViewOptions} to compare with this object.
+ * @return True if the {@link MarkerViewOptions} being passed in matches this
+ * {@link PolylineOptions} object. Else, false.
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
}
-
- @Override
- public int hashCode() {
- return marker != null ? marker.hashCode() : 0;
+ if (object == null || getClass() != object.getClass()) {
+ return false;
}
+ MarkerViewOptions that = (MarkerViewOptions) object;
+ return marker != null ? marker.equals(that.marker) : that.marker == null;
+ }
+
+ /**
+ * Gives an integer which can be used as the bucket number for storing elements of the set/map.
+ * This bucket number is the address of the element inside the set/map. There's no guarantee
+ * that this hash value will be consistent between different Java implementations, or even
+ * between different execution runs of the same program.
+ *
+ * @return integer value you can use for storing element.
+ */
+ @Override
+ public int hashCode() {
+ return marker != null ? marker.hashCode() : 0;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java
index a76238fdcb..2bd3c82786 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java
@@ -10,48 +10,62 @@ import java.util.List;
*/
public abstract class MultiPoint extends Annotation {
- private List<LatLng> points;
- private float alpha = 1.0f;
-
- protected MultiPoint() {
- super();
- points = new ArrayList<>();
- }
-
- /**
- * Returns a copy of the points.
- *
- * @return points - as a copy
- */
- public List<LatLng> getPoints() {
- return new ArrayList<>(points);
- }
-
- /**
- * Sets the points of this polyline. This method will take a copy
- * of the points, so further mutations to points will have no effect
- * on this polyline.
- *
- * @param points the points of the polyline
- */
- public void setPoints(List<LatLng> points) {
- this.points = new ArrayList<>(points);
- update();
- }
-
- public void addPoint(LatLng point) {
- points.add(point);
- update();
- }
-
- public float getAlpha() {
- return alpha;
- }
-
- public void setAlpha(float alpha) {
- this.alpha = alpha;
- update();
- }
-
- abstract void update();
+ private List<LatLng> points;
+ private float alpha = 1.0f;
+
+ protected MultiPoint() {
+ super();
+ points = new ArrayList<>();
+ }
+
+ /**
+ * Returns a copy of the points.
+ *
+ * @return A {@link List} of points.
+ */
+ public List<LatLng> getPoints() {
+ return new ArrayList<>(points);
+ }
+
+ /**
+ * Sets the points of this polyline. This method will take a copy of the points, so further
+ * mutations to points will have no effect on this polyline.
+ *
+ * @param points A {@link List} of {@link LatLng} points making up the polyline.
+ */
+ public void setPoints(List<LatLng> points) {
+ this.points = new ArrayList<>(points);
+ update();
+ }
+
+ /**
+ * Add a point to the polyline.
+ *
+ * @param point A {@link LatLng} point to be added.
+ */
+ public void addPoint(LatLng point) {
+ points.add(point);
+ update();
+ }
+
+ /**
+ * Value between 0 and 1 defining the polyline alpha.
+ *
+ * @return float value between 0 and 1.
+ */
+ public float getAlpha() {
+ return alpha;
+ }
+
+ /**
+ * Set this {@link MultiPoint}s alpha.
+ *
+ * @param alpha float value between 0 and 1.
+ */
+ public void setAlpha(float alpha) {
+ this.alpha = alpha;
+ update();
+ }
+
+ abstract void update();
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java
index 78e3a99e96..7b9de86bc4 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java
@@ -9,56 +9,56 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
*/
public final class Polygon extends MultiPoint {
- private int fillColor = Color.BLACK; // default fillColor is black
- private int strokeColor = Color.BLACK; // default strokeColor is black
+ private int fillColor = Color.BLACK; // default fillColor is black
+ private int strokeColor = Color.BLACK; // default strokeColor is black
- Polygon() {
- super();
- }
+ Polygon() {
+ super();
+ }
- /**
- * Get the color of the fill region of the polygon.
- *
- * @return the color of the fill
- */
- public int getFillColor() {
- return fillColor;
- }
+ /**
+ * Get the color of the fill region of the polygon.
+ *
+ * @return The color of the fill.
+ */
+ public int getFillColor() {
+ return fillColor;
+ }
- /**
- * Get the color fo the stroke of the polygon.
- *
- * @return the color of the stroke
- */
- public int getStrokeColor() {
- return strokeColor;
- }
+ /**
+ * Get the color fo the stroke of the polygon.
+ *
+ * @return The color of the stroke.
+ */
+ public int getStrokeColor() {
+ return strokeColor;
+ }
- /**
- * Sets the color of the fill region of the polygon.
- *
- * @param color - the color in ARGB format
- */
- public void setFillColor(int color) {
- fillColor = color;
- update();
- }
+ /**
+ * Sets the color of the fill region of the polygon.
+ *
+ * @param color The color in ARGB format.
+ */
+ public void setFillColor(int color) {
+ fillColor = color;
+ update();
+ }
- /**
- * Sets the color of the stroke of the polygon.
- *
- * @param color - the color in ARGB format
- */
- public void setStrokeColor(int color) {
- strokeColor = color;
- update();
- }
+ /**
+ * Sets the color of the stroke of the polygon.
+ *
+ * @param color The color in ARGB format.
+ */
+ public void setStrokeColor(int color) {
+ strokeColor = color;
+ update();
+ }
- @Override
- void update() {
- MapboxMap mapboxMap = getMapboxMap();
- if (mapboxMap != null) {
- mapboxMap.updatePolygon(this);
- }
+ @Override
+ void update() {
+ MapboxMap mapboxMap = getMapboxMap();
+ if (mapboxMap != null) {
+ mapboxMap.updatePolygon(this);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java
index 30847807b9..22f1258fc7 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java
@@ -14,138 +14,220 @@ import java.util.List;
*/
public final class PolygonOptions implements Parcelable {
- public static final Parcelable.Creator<PolygonOptions> CREATOR
- = new Parcelable.Creator<PolygonOptions>() {
- public PolygonOptions createFromParcel(Parcel in) {
- return new PolygonOptions(in);
- }
-
- public PolygonOptions[] newArray(int size) {
- return new PolygonOptions[size];
- }
+ public static final Parcelable.Creator<PolygonOptions> CREATOR =
+ new Parcelable.Creator<PolygonOptions>() {
+ public PolygonOptions createFromParcel(Parcel in) {
+ return new PolygonOptions(in);
+ }
+
+ public PolygonOptions[] newArray(int size) {
+ return new PolygonOptions[size];
+ }
};
- private PolygonOptions(Parcel in) {
- polygon = new Polygon();
- ArrayList<LatLng> pointsList = new ArrayList<>();
- in.readList(pointsList, LatLng.class.getClassLoader());
- addAll(pointsList);
- alpha(in.readFloat());
- fillColor(in.readInt());
- strokeColor(in.readInt());
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeList(getPoints());
- out.writeFloat(getAlpha());
- out.writeInt(getFillColor());
- out.writeInt(getStrokeColor());
- }
-
- private Polygon polygon;
-
- public PolygonOptions() {
- polygon = new Polygon();
- }
-
- public PolygonOptions add(LatLng point) {
- polygon.addPoint(point);
- return this;
- }
-
- public PolygonOptions add(LatLng... points) {
- for (LatLng point : points) {
- add(point);
- }
- return this;
- }
-
- public PolygonOptions addAll(Iterable<LatLng> points) {
- for (LatLng point : points) {
- add(point);
- }
- return this;
- }
-
- public PolygonOptions alpha(float alpha) {
- polygon.setAlpha(alpha);
- return this;
- }
-
- public float getAlpha() {
- return polygon.getAlpha();
- }
-
- /**
- * Sets the color of the polygon.
- *
- * @param color - the color in ARGB format
- * @return PolygonOptions - the options object
- */
- public PolygonOptions fillColor(int color) {
- polygon.setFillColor(color);
- return this;
- }
-
- public int getFillColor() {
- return polygon.getFillColor();
- }
-
- /**
- * Do not use this method. Used internally by the SDK.
- *
- * @return Polygon the Polygon to return
- */
- public Polygon getPolygon() {
- return polygon;
- }
-
- /**
- * Sets the color of the stroke of the polygon.
- *
- * @param color - the color in ARGB format
- * @return PolygonOptions - the options object
- */
- public PolygonOptions strokeColor(int color) {
- polygon.setStrokeColor(color);
- return this;
- }
-
- public int getStrokeColor() {
- return polygon.getStrokeColor();
- }
-
- public List<LatLng> getPoints() {
- // the getter gives us a copy, which is the safe thing to do...
- return polygon.getPoints();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- PolygonOptions polygon = (PolygonOptions) o;
-
- if (Float.compare(polygon.getAlpha(), getAlpha()) != 0) return false;
- if (getFillColor() != polygon.getFillColor()) return false;
- if (getStrokeColor() != polygon.getStrokeColor()) return false;
- return !(getPoints() != null ? !getPoints().equals(polygon.getPoints()) : polygon.getPoints() != null);
- }
-
- @Override
- public int hashCode() {
- int result = 1;
- result = 31 * result + (getAlpha() != +0.0f ? Float.floatToIntBits(getAlpha()) : 0);
- result = 31 * result + getFillColor();
- result = 31 * result + getStrokeColor();
- result = 31 * result + (getPoints() != null ? getPoints().hashCode() : 0);
- return result;
- }
+ private PolygonOptions(Parcel in) {
+ polygon = new Polygon();
+ ArrayList<LatLng> pointsList = new ArrayList<>();
+ in.readList(pointsList, LatLng.class.getClassLoader());
+ addAll(pointsList);
+ alpha(in.readFloat());
+ fillColor(in.readInt());
+ strokeColor(in.readInt());
+ }
+
+ /**
+ * Describe the kinds of special objects contained in this Parcelable's
+ * marshalled representation.
+ *
+ * @return integer 0.
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Flatten this object in to a Parcel.
+ *
+ * @param out The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written. May be 0 or
+ * {@link #PARCELABLE_WRITE_RETURN_VALUE}.
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeList(getPoints());
+ out.writeFloat(getAlpha());
+ out.writeInt(getFillColor());
+ out.writeInt(getStrokeColor());
+ }
+
+ private Polygon polygon;
+
+ /**
+ * Defines options for a polygon.
+ */
+ public PolygonOptions() {
+ polygon = new Polygon();
+ }
+
+ /**
+ * Adds a vertex to the outline of the polygon being built.
+ *
+ * @param point {@link LatLng} point to be added to polygon geometry.
+ * @return This {@link PolygonOptions} object with the given point added to the outline.
+ */
+ public PolygonOptions add(LatLng point) {
+ polygon.addPoint(point);
+ return this;
+ }
+
+ /**
+ * Adds vertices to the outline of the polygon being built.
+ *
+ * @param points {@link LatLng} points to be added to polygon geometry.
+ * @return This {@link PolygonOptions} object with the given points added to the outline.
+ */
+ public PolygonOptions add(LatLng... points) {
+ for (LatLng point : points) {
+ add(point);
+ }
+ return this;
+ }
+
+ /**
+ * Adds vertices to the outline of the polygon being built.
+ *
+ * @param points {@link Iterable} list made up of {@link LatLng} points defining the polygon
+ * geometry
+ * @return This {@link PolygonOptions} object with the given points added to the outline.
+ */
+ public PolygonOptions addAll(Iterable<LatLng> points) {
+ for (LatLng point : points) {
+ add(point);
+ }
+ return this;
+ }
+
+ /**
+ * Set the alpha value of the polyline.
+ *
+ * @param alpha float value between 0 (not visible) and 1.
+ * @return This {@link PolygonOptions} object with the given polygon alpha value.
+ */
+ public PolygonOptions alpha(float alpha) {
+ polygon.setAlpha(alpha);
+ return this;
+ }
+
+ /**
+ * Gets the alpha set for this {@link PolygonOptions} object.
+ *
+ * @return float value between 0 and 1 defining the alpha.
+ */
+ public float getAlpha() {
+ return polygon.getAlpha();
+ }
+
+ /**
+ * Specifies the polygon's fill color, as 32-bit ARGB. The default color is black.
+ *
+ * @param color 32-bit ARGB color.
+ * @return This {@link PolylineOptions} object with a new color set.
+ */
+ public PolygonOptions fillColor(int color) {
+ polygon.setFillColor(color);
+ return this;
+ }
+
+ /**
+ * Gets the fill color set for this {@link PolygonOptions} object.
+ *
+ * @return The fill color of the polygon in ARGB format.
+ */
+ public int getFillColor() {
+ return polygon.getFillColor();
+ }
+
+ /**
+ * Do not use this method. Used internally by the SDK.
+ *
+ * @return Polygon the Polygon to return
+ */
+ public Polygon getPolygon() {
+ return polygon;
+ }
+
+ /**
+ * Specifies the polygon's stroke color, as 32-bit ARGB. The default color is black.
+ *
+ * @param color 32-bit ARGB color.
+ * @return This {@link PolygonOptions} object with a new stroke color set.
+ */
+ public PolygonOptions strokeColor(int color) {
+ polygon.setStrokeColor(color);
+ return this;
+ }
+
+ /**
+ * Gets the stroke color set for this {@link PolygonOptions} object.
+ *
+ * @return The stroke color of the polygon in ARGB format.
+ */
+ public int getStrokeColor() {
+ return polygon.getStrokeColor();
+ }
+
+ public List<LatLng> getPoints() {
+ // the getter gives us a copy, which is the safe thing to do...
+ return polygon.getPoints();
+ }
+
+ /**
+ * Compares this {@link PolygonOptions} object with another {@link PolygonOptions} and
+ * determines if their color, alpha, stroke color, and vertices match.
+ *
+ * @param o Another {@link PolygonOptions} to compare with this object.
+ * @return True if color, alpha, stroke color, and vertices match this {@link PolygonOptions}
+ * object. Else, false.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ PolygonOptions polygon = (PolygonOptions) o;
+
+ if (Float.compare(polygon.getAlpha(), getAlpha()) != 0) {
+ return false;
+ }
+ if (getFillColor() != polygon.getFillColor()) {
+ return false;
+ }
+ if (getStrokeColor() != polygon.getStrokeColor()) {
+ return false;
+ }
+ return !(getPoints() != null ? !getPoints().equals(polygon.getPoints()) : polygon.getPoints() != null);
+ }
+
+ /**
+ * Gives an integer which can be used as the bucket number for storing elements of the set/map.
+ * This bucket number is the address of the element inside the set/map. There's no guarantee
+ * that this hash value will be consistent between different Java implementations, or even
+ * between different execution runs of the same program.
+ *
+ * @return integer value you can use for storing element.
+ */
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + (getAlpha() != +0.0f ? Float.floatToIntBits(getAlpha()) : 0);
+ result = 31 * result + getFillColor();
+ result = 31 * result + getStrokeColor();
+ result = 31 * result + (getPoints() != null ? getPoints().hashCode() : 0);
+ return result;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polyline.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polyline.java
index 4bf3242d57..a430d11009 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polyline.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polyline.java
@@ -9,56 +9,56 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
*/
public final class Polyline extends MultiPoint {
- private int color = Color.BLACK; // default color is black
- private float width = 10; // As specified by Google API Docs (in pixels)
+ private int color = Color.BLACK; // default color is black
+ private float width = 10; // As specified by Google API Docs (in pixels)
- Polyline() {
- super();
- }
+ Polyline() {
+ super();
+ }
- /**
- * Returns the Polyline tint color.
- *
- * @return the tint color
- */
- public int getColor() {
- return color;
- }
+ /**
+ * Gets the color of this polyline.
+ *
+ * @return The color in ARGB format.
+ */
+ public int getColor() {
+ return color;
+ }
- /**
- * Returns the Polyline width.
- *
- * @return the width
- */
- public float getWidth() {
- return width;
- }
+ /**
+ * Gets the width of this polyline.
+ *
+ * @return The width in screen pixels.
+ */
+ public float getWidth() {
+ return width;
+ }
- /**
- * Sets the color of the polyline.
- *
- * @param color - the color in ARGB format
- */
- public void setColor(int color) {
- this.color = color;
- update();
- }
+ /**
+ * Sets the color of the polyline.
+ *
+ * @param color - the color in ARGB format
+ */
+ public void setColor(int color) {
+ this.color = color;
+ update();
+ }
- /**
- * Sets the width of the polyline.
- *
- * @param width in pixels
- */
- public void setWidth(float width) {
- this.width = width;
- update();
- }
+ /**
+ * Sets the width of the polyline.
+ *
+ * @param width in pixels
+ */
+ public void setWidth(float width) {
+ this.width = width;
+ update();
+ }
- @Override
- void update() {
- MapboxMap mapboxMap = getMapboxMap();
- if (mapboxMap != null) {
- mapboxMap.updatePolyline(this);
- }
+ @Override
+ void update() {
+ MapboxMap mapboxMap = getMapboxMap();
+ if (mapboxMap != null) {
+ mapboxMap.updatePolyline(this);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolylineOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolylineOptions.java
index 1e625c10fc..ab22109a4e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolylineOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolylineOptions.java
@@ -14,137 +14,225 @@ import java.util.List;
public final class PolylineOptions implements Parcelable {
- public static final Parcelable.Creator<PolylineOptions> CREATOR
- = new Parcelable.Creator<PolylineOptions>() {
- public PolylineOptions createFromParcel(Parcel in) {
- return new PolylineOptions(in);
- }
-
- public PolylineOptions[] newArray(int size) {
- return new PolylineOptions[size];
- }
+ public static final Parcelable.Creator<PolylineOptions> CREATOR =
+ new Parcelable.Creator<PolylineOptions>() {
+ public PolylineOptions createFromParcel(Parcel in) {
+ return new PolylineOptions(in);
+ }
+
+ public PolylineOptions[] newArray(int size) {
+ return new PolylineOptions[size];
+ }
};
- private PolylineOptions(Parcel in) {
- polyline = new Polyline();
- ArrayList<LatLng> pointsList = new ArrayList<>();
- in.readList(pointsList, LatLng.class.getClassLoader());
- addAll(pointsList);
- alpha(in.readFloat());
- color(in.readInt());
- width(in.readFloat());
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeList(getPoints());
- out.writeFloat(getAlpha());
- out.writeInt(getColor());
- out.writeFloat(getWidth());
- }
-
- private Polyline polyline;
-
- public PolylineOptions() {
- polyline = new Polyline();
- }
-
- public PolylineOptions add(LatLng point) {
- polyline.addPoint(point);
- return this;
- }
-
- public PolylineOptions add(LatLng... points) {
- for (LatLng point : points) {
- add(point);
- }
- return this;
- }
-
- public PolylineOptions addAll(Iterable<LatLng> points) {
- for (LatLng point : points) {
- add(point);
- }
- return this;
- }
-
- public PolylineOptions alpha(float alpha) {
- polyline.setAlpha(alpha);
- return this;
- }
-
- public float getAlpha() {
- return polyline.getAlpha();
- }
-
- /**
- * Sets the color of the polyline.
- *
- * @param color - the color in ARGB format
- * @return PolyLineOptions The builder used to build a Polyline
- */
- public PolylineOptions color(int color) {
- polyline.setColor(color);
- return this;
- }
-
- public int getColor() {
- return polyline.getColor();
- }
-
- /**
- * Do not use this method. Used internally by the SDK.
- * @return PolyLine The polyline build by this class.
- */
- public Polyline getPolyline() {
- return polyline;
- }
-
- public float getWidth() {
- return polyline.getWidth();
- }
-
- /**
- * Sets the width of the polyline.
- *
- * @param width in pixels
- * @return a new PolylineOptions
- */
- public PolylineOptions width(float width) {
- polyline.setWidth(width);
- return this;
- }
-
- public List<LatLng> getPoints() {
- // the getter gives us a copy, which is the safe thing to do...
- return polyline.getPoints();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- PolylineOptions polyline = (PolylineOptions) o;
-
- if (Float.compare(polyline.getAlpha(), getAlpha()) != 0) return false;
- if (getColor() != polyline.getColor()) return false;
- if (Float.compare(polyline.getWidth(), getWidth()) != 0) return false;
- return !(getPoints() != null ? !getPoints().equals(polyline.getPoints()) : polyline.getPoints() != null);
- }
-
- @Override
- public int hashCode() {
- int result = 1;
- result = 31 * result + (getAlpha() != +0.0f ? Float.floatToIntBits(getAlpha()) : 0);
- result = 31 * result + getColor();
- result = 31 * result + (getWidth() != +0.0f ? Float.floatToIntBits(getWidth()) : 0);
- result = 31 * result + (getPoints() != null ? getPoints().hashCode() : 0);
- return result;
- }
+ private PolylineOptions(Parcel in) {
+ polyline = new Polyline();
+ ArrayList<LatLng> pointsList = new ArrayList<>();
+ in.readList(pointsList, LatLng.class.getClassLoader());
+ addAll(pointsList);
+ alpha(in.readFloat());
+ color(in.readInt());
+ width(in.readFloat());
+ }
+
+ /**
+ * Describe the kinds of special objects contained in this Parcelable's
+ * marshalled representation.
+ *
+ * @return integer 0.
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Flatten this object in to a Parcel.
+ *
+ * @param out The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written. May be 0 or
+ * {@link #PARCELABLE_WRITE_RETURN_VALUE}.
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeList(getPoints());
+ out.writeFloat(getAlpha());
+ out.writeInt(getColor());
+ out.writeFloat(getWidth());
+ }
+
+ private Polyline polyline;
+
+ /**
+ * Defines options for a polyline.
+ */
+ public PolylineOptions() {
+ polyline = new Polyline();
+ }
+
+ /**
+ * Adds a vertex to the end of the polyline being built.
+ *
+ * @param point {@link LatLng} point to be added to polyline geometry.
+ * @return This {@link PolylineOptions} object with the given point on the end.
+ */
+ public PolylineOptions add(LatLng point) {
+ polyline.addPoint(point);
+ return this;
+ }
+
+ /**
+ * Adds vertices to the end of the polyline being built.
+ *
+ * @param points {@link LatLng} points defining the polyline geometry.
+ * @return This {@link PolylineOptions} object with the given point on the end.
+ */
+ public PolylineOptions add(LatLng... points) {
+ for (LatLng point : points) {
+ add(point);
+ }
+ return this;
+ }
+
+ /**
+ * Adds vertices to the end of the polyline being built.
+ *
+ * @param points {@link Iterable} list made up of {@link LatLng} points defining the polyline
+ * geometry
+ * @return This {@link PolylineOptions} object with the given points on the end.
+ */
+ public PolylineOptions addAll(Iterable<LatLng> points) {
+ for (LatLng point : points) {
+ add(point);
+ }
+ return this;
+ }
+
+ /**
+ * Set the alpha value of the polyline.
+ *
+ * @param alpha float value between 0 (not visible) and 1.
+ * @return This {@link PolylineOptions} object with the given polyline alpha value.
+ */
+ public PolylineOptions alpha(float alpha) {
+ polyline.setAlpha(alpha);
+ return this;
+ }
+
+ /**
+ * Gets the alpha set for this {@link PolylineOptions} object.
+ *
+ * @return float value between 0 and 1 defining the alpha.
+ */
+ public float getAlpha() {
+ return polyline.getAlpha();
+ }
+
+ /**
+ * Sets the color of the polyline as a 32-bit ARGB color. The default color is black.
+ *
+ * @param color 32-bit ARGB color.
+ * @return This {@link PolylineOptions} object with a new color set.
+ */
+ public PolylineOptions color(int color) {
+ polyline.setColor(color);
+ return this;
+ }
+
+ /**
+ * Gets the color set for this {@link PolylineOptions} object.
+ *
+ * @return The color of the polyline in ARGB format.
+ */
+ public int getColor() {
+ return polyline.getColor();
+ }
+
+ /**
+ * Do not use this method. Used internally by the SDK.
+ *
+ * @return PolyLine The polyline build by this class.
+ */
+ public Polyline getPolyline() {
+ return polyline;
+ }
+
+ /**
+ * Gets the width set for this {@link PolylineOptions} object.
+ *
+ * @return The width of the polyline in screen pixels.
+ */
+ public float getWidth() {
+ return polyline.getWidth();
+ }
+
+ /**
+ * Sets the width of the polyline in screen pixels. The default is 10.
+ *
+ * @param width float value defining width of polyline using unit pixels.
+ * @return This {@link PolylineOptions} object with a new width set.
+ */
+ public PolylineOptions width(float width) {
+ polyline.setWidth(width);
+ return this;
+ }
+
+ /**
+ * Gets the points set for this {@link PolylineOptions} object.
+ *
+ * @return a {@link List} of {@link LatLng}s specifying the vertices of the polyline.
+ */
+ public List<LatLng> getPoints() {
+ // the getter gives us a copy, which is the safe thing to do...
+ return polyline.getPoints();
+ }
+
+ /**
+ * Compares this {@link PolylineOptions} object with another {@link PolylineOptions} and
+ * determines if their color, alpha, width, and vertices match.
+ *
+ * @param o Another {@link PolylineOptions} to compare with this object.
+ * @return True if color, alpha, width, and vertices match this {@link PolylineOptions} object.
+ * Else, false.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ PolylineOptions polyline = (PolylineOptions) o;
+
+ if (Float.compare(polyline.getAlpha(), getAlpha()) != 0) {
+ return false;
+ }
+ if (getColor() != polyline.getColor()) {
+ return false;
+ }
+ if (Float.compare(polyline.getWidth(), getWidth()) != 0) {
+ return false;
+ }
+ return !(getPoints() != null ? !getPoints().equals(polyline.getPoints()) : polyline.getPoints() != null);
+ }
+
+ /**
+ * Gives an integer which can be used as the bucket number for storing elements of the set/map.
+ * This bucket number is the address of the element inside the set/map. There's no guarantee
+ * that this hash value will be consistent between different Java implementations, or even
+ * between different execution runs of the same program.
+ *
+ * @return integer value you can use for storing element.
+ */
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + (getAlpha() != +0.0f ? Float.floatToIntBits(getAlpha()) : 0);
+ result = 31 * result + getColor();
+ result = 31 * result + (getWidth() != +0.0f ? Float.floatToIntBits(getWidth()) : 0);
+ result = 31 * result + (getPoints() != null ? getPoints().hashCode() : 0);
+ return result;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java
index 3888abc041..79045b68bb 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java
@@ -9,268 +9,311 @@ import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.utils.MathUtils;
+import static com.mapbox.mapboxsdk.utils.MathUtils.convertNativeBearing;
+
/**
* Resembles the position, angle, zoom and tilt of the user's viewpoint.
*/
public final class CameraPosition implements Parcelable {
- public static final Parcelable.Creator<CameraPosition> CREATOR
- = new Parcelable.Creator<CameraPosition>() {
- public CameraPosition createFromParcel(Parcel in) {
- double bearing = in.readDouble();
- LatLng target = in.readParcelable(LatLng.class.getClassLoader());
- double tilt = in.readDouble();
- double zoom = in.readDouble();
- return new CameraPosition(target, zoom, tilt, bearing);
- }
-
- public CameraPosition[] newArray(int size) {
- return new CameraPosition[size];
- }
+ public static final CameraPosition DEFAULT = new CameraPosition(new LatLng(), 0, 0, 0);
+
+ public static final Parcelable.Creator<CameraPosition> CREATOR =
+ new Parcelable.Creator<CameraPosition>() {
+ public CameraPosition createFromParcel(Parcel in) {
+ double bearing = in.readDouble();
+ LatLng target = in.readParcelable(LatLng.class.getClassLoader());
+ double tilt = in.readDouble();
+ double zoom = in.readDouble();
+ return new CameraPosition(target, zoom, tilt, bearing);
+ }
+
+ public CameraPosition[] newArray(int size) {
+ return new CameraPosition[size];
+ }
};
+ /**
+ * Direction that the camera is pointing in, in degrees clockwise from north.
+ */
+ public final double bearing;
+
+ /**
+ * The location that the camera is pointing at.
+ */
+ public final LatLng target;
+
+ /**
+ * The angle, in degrees, of the camera angle from the nadir (directly facing the Earth).
+ * See tilt(float) for details of restrictions on the range of values.
+ */
+ public final double tilt;
+
+ /**
+ * Zoom level near the center of the screen. See zoom(float) for the definition of the camera's
+ * zoom level.
+ */
+ public final double zoom;
+
+ /**
+ * Constructs a CameraPosition.
+ *
+ * @param target The target location to align with the center of the screen.
+ * @param zoom Zoom level at target. See zoom(float) for details of restrictions.
+ * @param tilt The camera angle, in degrees, from the nadir (directly down). See tilt(float)
+ * for details of restrictions.
+ * @param bearing Direction that the camera is pointing in, in degrees clockwise from north.
+ * This value will be normalized to be within 0 degrees inclusive and 360 degrees
+ * exclusive.
+ * @throws NullPointerException if target is null
+ * @throws IllegalArgumentException if tilt is outside the range of 0 to 90 degrees inclusive.
+ */
+ CameraPosition(LatLng target, double zoom, double tilt, double bearing) {
+ this.target = target;
+ this.bearing = bearing;
+ this.tilt = tilt;
+ this.zoom = zoom;
+ }
+
+ /**
+ * Describe the kinds of special objects contained in this Parcelable's
+ * marshalled representation.
+ *
+ * @return integer 0.
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Flatten this object in to a Parcel.
+ *
+ * @param out The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written. May be 0 or
+ * {@link #PARCELABLE_WRITE_RETURN_VALUE}.
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeDouble(bearing);
+ out.writeParcelable(target, flags);
+ out.writeDouble(tilt);
+ out.writeDouble(zoom);
+ }
+
+ /**
+ * Returns a String with the camera target, zoom, bearing and tilt.
+ *
+ * @return A String with CameraPosition information.
+ */
+ @Override
+ public String toString() {
+ return "Target: " + target + ", Zoom:" + zoom + ", Bearing:" + bearing + ", Tilt:" + tilt;
+ }
+
+ /**
+ * Compares this {@link CameraPosition} object with another {@link CameraPosition} and
+ * determines if their target, zoom, tilt, and bearing match.
+ *
+ * @param o Another {@link CameraPosition} to compare with this object.
+ * @return True if target, zoom, tilt, and bearing match this {@link CameraPosition} object.
+ * Else, false.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ CameraPosition cameraPosition = (CameraPosition) o;
+ if (target != null && !target.equals(cameraPosition.target)) {
+ return false;
+ } else if (zoom != cameraPosition.zoom) {
+ return false;
+ } else if (tilt != cameraPosition.tilt) {
+ return false;
+ } else if (bearing != cameraPosition.bearing) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Gives an integer which can be used as the bucket number for storing elements of the set/map.
+ * This bucket number is the address of the element inside the set/map. There's no guarantee
+ * that this hash value will be consistent between different Java implementations, or even
+ * between different execution runs of the same program.
+ *
+ * @return integer value you can use for storing element.
+ */
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + (target != null ? target.hashCode() : 0);
+ return result;
+ }
+
+ /**
+ * Builder for composing {@link CameraPosition} objects.
+ */
+ public static final class Builder {
+
+ private double bearing = -1;
+ private LatLng target = null;
+ private double tilt = -1;
+ private double zoom = -1;
+
/**
- * Direction that the camera is pointing in, in degrees clockwise from north.
+ * Creates an empty builder.
*/
- public final double bearing;
+ public Builder() {
+ super();
+ }
/**
- * The location that the camera is pointing at.
+ * Create Builder with an existing CameraPosition data.
+ *
+ * @param previous Existing CameraPosition values to use
*/
- public final LatLng target;
+ public Builder(CameraPosition previous) {
+ super();
+ if (previous != null) {
+ this.bearing = previous.bearing;
+ this.target = previous.target;
+ this.tilt = previous.tilt;
+ this.zoom = previous.zoom;
+ }
+ }
/**
- * The angle, in degrees, of the camera angle from the nadir (directly facing the Earth). See tilt(float) for details of restrictions on the range of values.
+ * Create Builder with an existing CameraPosition data.
+ *
+ * @param typedArray TypedArray containgin attribute values
*/
- public final double tilt;
+ public Builder(TypedArray typedArray) {
+ super();
+ if (typedArray != null) {
+ this.bearing = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraBearing, 0.0f);
+ double lat = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraTargetLat, 0.0f);
+ double lng = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraTargetLng, 0.0f);
+ this.target = new LatLng(lat, lng);
+ this.tilt = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraTilt, 0.0f);
+ this.zoom = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraZoom, 0.0f);
+ }
+ }
/**
- * Zoom level near the center of the screen. See zoom(float) for the definition of the camera's zoom level.
+ * Create Builder from an existing CameraPositionUpdate update.
+ *
+ * @param update Update containing camera options
*/
- public final double zoom;
+ public Builder(CameraUpdateFactory.CameraPositionUpdate update) {
+ super();
+ if (update != null) {
+ bearing = update.getBearing();
+ target = update.getTarget();
+ tilt = update.getTilt();
+ zoom = update.getZoom();
+ }
+ }
/**
- * Constructs a CameraPosition.
+ * Create Builder from an existing CameraPositionUpdate update.
*
- * @param target The target location to align with the center of the screen.
- * @param zoom Zoom level at target. See zoom(float) for details of restrictions.
- * @param tilt The camera angle, in degrees, from the nadir (directly down). See tilt(float) for details of restrictions.
- * @param bearing Direction that the camera is pointing in, in degrees clockwise from north. This value will be normalized to be within 0 degrees inclusive and 360 degrees exclusive.
- * @throws NullPointerException if target is null
- * @throws IllegalArgumentException if tilt is outside the range of 0 to 90 degrees inclusive.
+ * @param update Update containing camera options
*/
- CameraPosition(LatLng target, double zoom, double tilt, double bearing) {
- this.target = target;
- this.bearing = bearing;
- this.tilt = tilt;
- this.zoom = zoom;
+ public Builder(CameraUpdateFactory.ZoomUpdate update) {
+ super();
+ if (update != null) {
+ this.zoom = update.getZoom();
+ }
}
- @Override
- public int describeContents() {
- return 0;
+ /**
+ * Create Builder from an existing array of doubles.
+ * <p>
+ * These values conform to map.ccp representation of a camera position.
+ * </p>
+ *
+ * @param nativeCameraValues Values containing target, bearing, tilt and zoom
+ */
+ public Builder(double[] nativeCameraValues) {
+ super();
+ if (nativeCameraValues != null && nativeCameraValues.length == 5) {
+ target(new LatLng(nativeCameraValues[0], nativeCameraValues[1]));
+ bearing(convertNativeBearing(nativeCameraValues[2]));
+ tilt(nativeCameraValues[3]);
+ zoom(nativeCameraValues[4]);
+ }
}
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeDouble(bearing);
- out.writeParcelable(target, flags);
- out.writeDouble(tilt);
- out.writeDouble(zoom);
+ /**
+ * Sets the direction that the camera is pointing in, in degrees clockwise from north.
+ *
+ * @param bearing Bearing
+ * @return Builder
+ */
+ public Builder bearing(double bearing) {
+ double direction = bearing;
+
+ while (direction >= 360) {
+ direction -= 360;
+ }
+ while (direction < 0) {
+ direction += 360;
+ }
+
+ this.bearing = direction;
+ return this;
}
- @Override
- public String toString() {
- return "Target: " + target + ", Zoom:" + zoom + ", Bearing:" + bearing + ", Tilt:" + tilt;
+ /**
+ * Builds a CameraPosition.
+ *
+ * @return CameraPosition
+ */
+ public CameraPosition build() {
+ return new CameraPosition(target, zoom, tilt, bearing);
}
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- CameraPosition cameraPosition = (CameraPosition) o;
- if (target != null && !target.equals(cameraPosition.target)) {
- return false;
- } else if (zoom != cameraPosition.zoom) {
- return false;
- } else if (tilt != cameraPosition.tilt) {
- return false;
- } else if (bearing != cameraPosition.bearing) {
- return false;
- }
- return true;
+ /**
+ * Sets the location that the camera is pointing at.
+ *
+ * @param location Location
+ * @return Builder
+ */
+ public Builder target(LatLng location) {
+ this.target = location;
+ return this;
}
- @Override
- public int hashCode() {
- int result = 1;
- result = 31 * result + (target != null ? target.hashCode() : 0);
- return result;
+ /**
+ * Set the tilt in degrees
+ * <p>
+ * value is clamped to 0 and 60.
+ * <p/>
+ *
+ * @param tilt Tilt value
+ * @return Builder
+ */
+ public Builder tilt(double tilt) {
+ this.tilt = MathUtils.clamp(tilt, MapboxConstants.MINIMUM_TILT, MapboxConstants.MAXIMUM_TILT);
+ return this;
}
/**
- * Builder for composing {@link CameraPosition} objects.
+ * Set the zoom
+ *
+ * @param zoom Zoom value
+ * @return Builder
*/
- public static final class Builder {
-
- private double bearing = -1;
- private LatLng target = null;
- private double tilt = -1;
- private double zoom = -1;
-
- /**
- * Creates an empty builder.
- */
- public Builder() {
- super();
- }
-
- /**
- * Create Builder with an existing CameraPosition data.
- *
- * @param previous Existing CameraPosition values to use
- */
- public Builder(CameraPosition previous) {
- super();
- if (previous != null) {
- this.bearing = previous.bearing;
- this.target = previous.target;
- this.tilt = previous.tilt;
- this.zoom = previous.zoom;
- }
- }
-
- /**
- * Create Builder with an existing CameraPosition data.
- *
- * @param typedArray TypedArray containgin attribute values
- */
- public Builder(TypedArray typedArray) {
- super();
- if (typedArray != null) {
- this.bearing = typedArray.getFloat(R.styleable.MapView_direction, 0.0f);
- double lat = typedArray.getFloat(R.styleable.MapView_center_latitude, 0.0f);
- double lng = typedArray.getFloat(R.styleable.MapView_center_longitude, 0.0f);
- this.target = new LatLng(lat, lng);
- this.tilt = typedArray.getFloat(R.styleable.MapView_tilt, 0.0f);
- this.zoom = typedArray.getFloat(R.styleable.MapView_zoom, 0.0f);
- }
- }
-
- /**
- * Create Builder from an existing CameraPositionUpdate update.
- *
- * @param update Update containing camera options
- */
- public Builder(CameraUpdateFactory.CameraPositionUpdate update) {
- super();
- if (update != null) {
- bearing = update.getBearing();
- target = update.getTarget();
- tilt = update.getTilt();
- zoom = update.getZoom();
- }
- }
-
- /**
- * Create Builder from an existing CameraPositionUpdate update.
- *
- * @param update Update containing camera options
- */
- public Builder(CameraUpdateFactory.ZoomUpdate update) {
- super();
- if (update != null) {
- this.zoom = update.getZoom();
- }
- }
-
- /**
- * Create Builder from an existing array of doubles.
- * <p>
- * These values conform to map.ccp representation of a camera position.
- * </p>
- *
- * @param nativeCameraValues Values containing target, bearing, tilt and zoom
- */
- public Builder(double[] nativeCameraValues) {
- super();
- if (nativeCameraValues != null && nativeCameraValues.length == 5) {
- target(new LatLng(nativeCameraValues[0], nativeCameraValues[1]));
- bearing(nativeCameraValues[2]);
- tilt(nativeCameraValues[3]);
- zoom((float) nativeCameraValues[4]);
- }
- }
-
- /**
- * Sets the direction that the camera is pointing in, in degrees clockwise from north.
- *
- * @param bearing Bearing
- * @return Builder
- */
- public Builder bearing(double bearing) {
- double direction = bearing;
-
- while (direction >= 360) {
- direction -= 360;
- }
- while (direction < 0) {
- direction += 360;
- }
-
- this.bearing = direction;
- return this;
- }
-
- /**
- * Builds a CameraPosition.
- *
- * @return CameraPosition
- */
- public CameraPosition build() {
- return new CameraPosition(target, zoom, tilt, bearing);
- }
-
- /**
- * Sets the location that the camera is pointing at.
- *
- * @param location Location
- * @return Builder
- */
- public Builder target(LatLng location) {
- this.target = location;
- return this;
- }
-
- /**
- * Set the tilt in degrees
- * <p>
- * value is clamped to 0 and 60.
- * <p/>
- *
- * @param tilt Tilt value
- * @return Builder
- */
- public Builder tilt(double tilt) {
- this.tilt = (float) MathUtils.clamp(tilt, MapboxConstants.MINIMUM_TILT, MapboxConstants.MAXIMUM_TILT);
- return this;
- }
-
- /**
- * Set the zoom
- *
- * @param zoom Zoom value
- * @return Builder
- */
- public Builder zoom(double zoom) {
- this.zoom = zoom;
- return this;
- }
+ public Builder zoom(double zoom) {
+ this.zoom = zoom;
+ return this;
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java
index 94ee4912ce..7e0dbf08fb 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java
@@ -9,6 +9,6 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
*/
public interface CameraUpdate {
- CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap);
+ CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
index db05486bc2..aecc51530b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
@@ -21,386 +21,397 @@ import java.lang.annotation.RetentionPolicy;
*/
public final class CameraUpdateFactory {
- /**
- * Returns a CameraUpdate that moves the camera to a specified CameraPosition.
- *
- * @param cameraPosition Camera Position to change to
- * @return CameraUpdate Final Camera Position
- */
- public static CameraUpdate newCameraPosition(@NonNull CameraPosition cameraPosition) {
- return new CameraPositionUpdate(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom);
+ /**
+ * Returns a CameraUpdate that moves the camera to a specified CameraPosition.
+ *
+ * @param cameraPosition Camera Position to change to
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate newCameraPosition(@NonNull CameraPosition cameraPosition) {
+ return new CameraPositionUpdate(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt,
+ cameraPosition.zoom);
+ }
+
+ /**
+ * Returns a CameraUpdate that moves the center of the screen to a latitude and longitude
+ * specified by a LatLng object. This centers the camera on the LatLng object.
+ *
+ * @param latLng Target location to change to
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate newLatLng(@NonNull LatLng latLng) {
+ return new CameraPositionUpdate(-1, latLng, -1, -1);
+ }
+
+ /**
+ * Returns a {@link CameraUpdate} that transforms the camera such that the specified
+ * latitude/longitude bounds are centered on screen at the greatest possible zoom level.
+ * You can specify padding, in order to inset the bounding box from the map view's edges.
+ * The returned CameraUpdate has a bearing of 0 and a tilt of 0.
+ *
+ * @param bounds Bounds to match Camera position with
+ * @param padding Padding added to the bounds
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int padding) {
+ return newLatLngBounds(bounds, padding, padding, padding, padding);
+ }
+
+ /**
+ * Returns a {@link CameraUpdate} that transforms the camera such that the specified
+ * latitude/longitude bounds are centered on screen at the greatest possible zoom level.
+ * You can specify padding, in order to inset the bounding box from the map view's edges.
+ * The returned CameraUpdate has a bearing of 0 and a tilt of 0.
+ *
+ * @param bounds Bounds to base the Camera position out of
+ * @param paddingLeft Padding left of the bounds
+ * @param paddingTop Padding top of the bounds
+ * @param paddingRight Padding right of the bounds
+ * @param paddingBottom Padding bottom of the bounds
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int paddingLeft, int paddingTop,
+ int paddingRight, int paddingBottom) {
+ return new CameraBoundsUpdate(bounds, paddingLeft, paddingTop, paddingRight, paddingBottom);
+ }
+
+ /**
+ * Returns a CameraUpdate that moves the center of the screen to a latitude and longitude
+ * specified by a LatLng object, and moves to the given zoom level.
+ *
+ * @param latLng Target location to change to
+ * @param zoom Zoom level to change to
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate newLatLngZoom(@NonNull LatLng latLng, double zoom) {
+ return new CameraPositionUpdate(-1, latLng, -1, zoom);
+ }
+
+ /**
+ * Returns a CameraUpdate that scrolls the camera over the map,
+ * shifting the center of view by the specified number of pixels in the x and y directions.
+ *
+ * @param xPixel Amount of pixels to scroll to in x direction
+ * @param yPixel Amount of pixels to scroll to in y direction
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate scrollBy(float xPixel, float yPixel) {
+ return new CameraMoveUpdate(xPixel, yPixel);
+ }
+
+ /**
+ * Returns a CameraUpdate that shifts the zoom level of the current camera viewpoint.
+ *
+ * @param amount Amount of zoom level to change with
+ * @param focus Focus point of zoom
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate zoomBy(double amount, Point focus) {
+ return new ZoomUpdate(amount, focus.x, focus.y);
+ }
+
+ /**
+ * Returns a CameraUpdate that shifts the zoom level of the current camera viewpoint.
+ *
+ * @param amount Amount of zoom level to change with
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate zoomBy(double amount) {
+ return new ZoomUpdate(ZoomUpdate.ZOOM_BY, amount);
+ }
+
+ /**
+ * Returns a CameraUpdate that zooms in on the map by moving the viewpoint's height closer to
+ * the Earth's surface. The zoom increment is 1.0.
+ *
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate zoomIn() {
+ return new ZoomUpdate(ZoomUpdate.ZOOM_IN);
+ }
+
+ /**
+ * Returns a CameraUpdate that zooms out on the map by moving the viewpoint's height farther
+ * away from the Earth's surface. The zoom increment is -1.0.
+ *
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate zoomOut() {
+ return new ZoomUpdate(ZoomUpdate.ZOOM_OUT);
+ }
+
+ /**
+ * Returns a CameraUpdate that moves the camera viewpoint to a particular zoom level.
+ *
+ * @param zoom Zoom level to change to
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate zoomTo(double zoom) {
+ return new ZoomUpdate(ZoomUpdate.ZOOM_TO, zoom);
+ }
+
+ //
+ // CameraUpdate types
+ //
+
+ static final class CameraPositionUpdate implements CameraUpdate {
+
+ private final double bearing;
+ private final LatLng target;
+ private final double tilt;
+ private final double zoom;
+
+ CameraPositionUpdate(double bearing, LatLng target, double tilt, double zoom) {
+ this.bearing = bearing;
+ this.target = target;
+ this.tilt = tilt;
+ this.zoom = zoom;
}
- /**
- * Returns a CameraUpdate that moves the center of the screen to a latitude and longitude
- * specified by a LatLng object. This centers the camera on the LatLng object.
- *
- * @param latLng Target location to change to
- * @return CameraUpdate Final Camera Position
- */
- public static CameraUpdate newLatLng(@NonNull LatLng latLng) {
- return new CameraPositionUpdate(-1, latLng, -1, -1);
+ public LatLng getTarget() {
+ return target;
}
- /**
- * Returns a CameraUpdate that transforms the camera such that the specified latitude/longitude
- * bounds are centered on screen at the greatest possible zoom level.
- * You can specify padding, in order to inset the bounding box from the map view's edges.
- * The returned CameraUpdate has a bearing of 0 and a tilt of 0.
- *
- * @param bounds Bounds to match Camera position with
- * @param padding Padding added to the bounds
- * @return CameraUpdate Final Camera Position
- */
- public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int padding) {
- return newLatLngBounds(bounds, padding, padding, padding, padding);
+ public double getBearing() {
+ return bearing;
}
- /**
- * Returns a CameraUpdate that transforms the camera such that the specified latitude/longitude
- * bounds are centered on screen at the greatest possible zoom level.
- * You can specify padding, in order to inset the bounding box from the map view's edges.
- * The returned CameraUpdate has a bearing of 0 and a tilt of 0.
- *
- * @param bounds Bounds to base the Camera position out of
- * @param paddingLeft Padding left of the bounds
- * @param paddingTop Padding top of the bounds
- * @param paddingRight Padding right of the bounds
- * @param paddingBottom Padding bottom of the bounds
- * @return CameraUpdate Final Camera Position
- */
- public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
- return new CameraBoundsUpdate(bounds, paddingLeft, paddingTop, paddingRight, paddingBottom);
+ public double getTilt() {
+ return tilt;
}
- /**
- * Returns a CameraUpdate that moves the center of the screen to a latitude and longitude specified by a LatLng object,
- * and moves to the given zoom level.
- *
- * @param latLng Target location to change to
- * @param zoom Zoom level to change to
- * @return CameraUpdate Final Camera Position
- */
- public static CameraUpdate newLatLngZoom(@NonNull LatLng latLng, float zoom) {
- return new CameraPositionUpdate(-1, latLng, -1, zoom);
+ public double getZoom() {
+ return zoom;
}
- /**
- * Returns a CameraUpdate that scrolls the camera over the map,
- * shifting the center of view by the specified number of pixels in the x and y directions.
- *
- * @param xPixel Amount of pixels to scroll to in x direction
- * @param yPixel Amount of pixels to scroll to in y direction
- * @return CameraUpdate Final Camera Position
- */
- public static CameraUpdate scrollBy(float xPixel, float yPixel) {
- return new CameraMoveUpdate(xPixel, yPixel);
+ @Override
+ public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
+ CameraPosition previousPosition = mapboxMap.getCameraPosition();
+ if (target == null) {
+ return new CameraPosition.Builder(this)
+ .target(previousPosition.target)
+ .build();
+ }
+ return new CameraPosition.Builder(this).build();
}
+ }
- /**
- * Returns a CameraUpdate that shifts the zoom level of the current camera viewpoint.
- *
- * @param amount Amount of zoom level to change with
- * @param focus Focus point of zoom
- * @return CameraUpdate Final Camera Position
- */
- public static CameraUpdate zoomBy(float amount, Point focus) {
- return new ZoomUpdate(amount, focus.x, focus.y);
+ static final class CameraBoundsUpdate implements CameraUpdate {
+
+ private LatLngBounds bounds;
+ private RectF padding;
+
+ CameraBoundsUpdate(LatLngBounds bounds, RectF padding) {
+ this.bounds = bounds;
+ this.padding = padding;
}
- /**
- * Returns a CameraUpdate that shifts the zoom level of the current camera viewpoint.
- *
- * @param amount Amount of zoom level to change with
- * @return CameraUpdate Final Camera Position
- */
- public static CameraUpdate zoomBy(float amount) {
- return new ZoomUpdate(ZoomUpdate.ZOOM_BY, amount);
+ CameraBoundsUpdate(LatLngBounds bounds, int[] padding) {
+ this(bounds, new RectF(padding[0], padding[1], padding[2], padding[3]));
}
- /**
- * Returns a CameraUpdate that zooms in on the map by moving the viewpoint's height closer to the Earth's surface. The zoom increment is 1.0.
- *
- * @return CameraUpdate Final Camera Position
- */
- public static CameraUpdate zoomIn() {
- return new ZoomUpdate(ZoomUpdate.ZOOM_IN);
+ CameraBoundsUpdate(LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
+ this(bounds, new int[] {paddingLeft, paddingTop, paddingRight, paddingBottom});
}
- /**
- * Returns a CameraUpdate that zooms out on the map by moving the viewpoint's height farther away from the Earth's surface. The zoom increment is -1.0.
- *
- * @return CameraUpdate Final Camera Position
- */
- public static CameraUpdate zoomOut() {
- return new ZoomUpdate(ZoomUpdate.ZOOM_OUT);
+ public LatLngBounds getBounds() {
+ return bounds;
+ }
+
+ public RectF getPadding() {
+ return padding;
+ }
+
+ @Override
+ public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
+ // Get required objects
+ Projection projection = mapboxMap.getProjection();
+ UiSettings uiSettings = mapboxMap.getUiSettings();
+
+ // calculate correct padding
+ int[] mapPadding = mapboxMap.getPadding();
+ RectF latLngPadding = getPadding();
+ RectF padding = new RectF(latLngPadding.left + mapPadding[0],
+ latLngPadding.top + mapPadding[1],
+ latLngPadding.right + mapPadding[2],
+ latLngPadding.bottom + mapPadding[3]);
+
+ // Calculate the bounds of the possibly rotated shape with respect to the viewport
+ PointF nePixel = new PointF(-Float.MAX_VALUE, -Float.MAX_VALUE);
+ PointF swPixel = new PointF(Float.MAX_VALUE, Float.MAX_VALUE);
+ float viewportHeight = uiSettings.getHeight();
+ for (LatLng latLng : getBounds().toLatLngs()) {
+ PointF pixel = projection.toScreenLocation(latLng);
+ swPixel.x = Math.min(swPixel.x, pixel.x);
+ nePixel.x = Math.max(nePixel.x, pixel.x);
+ swPixel.y = Math.min(swPixel.y, viewportHeight - pixel.y);
+ nePixel.y = Math.max(nePixel.y, viewportHeight - pixel.y);
+ }
+
+ // Calculate width/height
+ float width = nePixel.x - swPixel.x;
+ float height = nePixel.y - swPixel.y;
+
+ double zoom = 0;
+ float minScale = 1;
+ // Calculate the zoom level
+ if (padding != null) {
+ float scaleX = (uiSettings.getWidth() - padding.left - padding.right) / width;
+ float scaleY = (uiSettings.getHeight() - padding.top - padding.bottom) / height;
+ minScale = scaleX < scaleY ? scaleX : scaleY;
+ zoom = calculateZoom(mapboxMap, minScale);
+ zoom = MathUtils.clamp(zoom, mapboxMap.getMinZoomLevel(), mapboxMap.getMaxZoomLevel());
+ }
+
+ // Calculate the center point
+ PointF paddedNEPixel = new PointF(nePixel.x + padding.right / minScale, nePixel.y + padding.top / minScale);
+ PointF paddedSWPixel = new PointF(swPixel.x - padding.left / minScale, swPixel.y - padding.bottom / minScale);
+ PointF centerPixel = new PointF((paddedNEPixel.x + paddedSWPixel.x) / 2, (paddedNEPixel.y + paddedSWPixel.y) / 2);
+ centerPixel.y = viewportHeight - centerPixel.y;
+ LatLng center = projection.fromScreenLocation(centerPixel);
+
+ return new CameraPosition.Builder()
+ .target(center)
+ .zoom(zoom)
+ .tilt(0)
+ .bearing(0)
+ .build();
}
/**
- * Returns a CameraUpdate that moves the camera viewpoint to a particular zoom level.
+ * Calculates a zoom level based on minimum scale and current scale from MapView
*
- * @param zoom Zoom level to change to
- * @return CameraUpdate Final Camera Position
+ * @param minScale The minimum scale to calculate the zoom level.
+ * @return zoom level that fits the MapView.
*/
- public static CameraUpdate zoomTo(float zoom) {
- return new ZoomUpdate(ZoomUpdate.ZOOM_TO, zoom);
+ public double calculateZoom(MapboxMap mapboxMap, float minScale) {
+ return Math.log(mapboxMap.getCameraPosition().zoom * minScale) / Math.log(2);
+ }
+ }
+
+ static final class CameraMoveUpdate implements CameraUpdate {
+
+ private float x;
+ private float y;
+
+ CameraMoveUpdate(float x, float y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ @Override
+ public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
+ UiSettings uiSettings = mapboxMap.getUiSettings();
+ Projection projection = mapboxMap.getProjection();
+
+ // Calculate the new center point
+ float viewPortWidth = uiSettings.getWidth();
+ float viewPortHeight = uiSettings.getHeight();
+ PointF targetPoint = new PointF(viewPortWidth / 2 + x, viewPortHeight / 2 + y);
+
+ // Convert point to LatLng
+ LatLng latLng = projection.fromScreenLocation(targetPoint);
+
+ CameraPosition previousPosition = mapboxMap.getCameraPosition();
+ return new CameraPosition.Builder()
+ .target(latLng != null ? latLng : previousPosition.target)
+ .zoom(previousPosition.zoom)
+ .tilt(previousPosition.tilt)
+ .bearing(previousPosition.bearing)
+ .build();
+ }
+ }
+
+ static final class ZoomUpdate implements CameraUpdate {
+
+ @IntDef( {ZOOM_IN, ZOOM_OUT, ZOOM_BY, ZOOM_TO, ZOOM_TO_POINT})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface Type {
+ }
+
+ static final int ZOOM_IN = 0;
+ static final int ZOOM_OUT = 1;
+ static final int ZOOM_BY = 2;
+ static final int ZOOM_TO = 3;
+ static final int ZOOM_TO_POINT = 4;
+
+ @Type
+ private final int type;
+ private final double zoom;
+ private float x;
+ private float y;
+
+ ZoomUpdate(@Type int type) {
+ this.type = type;
+ this.zoom = 0;
+ }
+
+ ZoomUpdate(@Type int type, double zoom) {
+ this.type = type;
+ this.zoom = zoom;
+ }
+
+ ZoomUpdate(double zoom, float x, float y) {
+ this.type = ZOOM_TO_POINT;
+ this.zoom = zoom;
+ this.x = x;
+ this.y = y;
+ }
+
+ public double getZoom() {
+ return zoom;
+ }
+
+ @Type
+ public int getType() {
+ return type;
}
- //
- // CameraUpdate types
- //
-
- static final class CameraPositionUpdate implements CameraUpdate {
-
- private final double bearing;
- private final LatLng target;
- private final double tilt;
- private final double zoom;
-
- CameraPositionUpdate(double bearing, LatLng target, double tilt, double zoom) {
- this.bearing = bearing;
- this.target = target;
- this.tilt = tilt;
- this.zoom = zoom;
- }
-
- public LatLng getTarget() {
- return target;
- }
-
- public double getBearing() {
- return bearing;
- }
-
- public double getTilt() {
- return tilt;
- }
-
- public double getZoom() {
- return zoom;
- }
-
- @Override
- public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
- CameraPosition previousPosition = mapboxMap.getCameraPosition();
- if (target == null) {
- return new CameraPosition.Builder()
- .tilt(tilt)
- .zoom(zoom)
- .bearing(bearing)
- .target(previousPosition.target)
- .build();
- }
- return new CameraPosition.Builder(this).build();
- }
+ public float getX() {
+ return x;
}
- static final class CameraBoundsUpdate implements CameraUpdate {
-
- private LatLngBounds bounds;
- private RectF padding;
-
- CameraBoundsUpdate(LatLngBounds bounds, RectF padding) {
- this.bounds = bounds;
- this.padding = padding;
- }
-
- CameraBoundsUpdate(LatLngBounds bounds, int[] padding) {
- this(bounds, new RectF(padding[0], padding[1], padding[2], padding[3]));
- }
-
- CameraBoundsUpdate(LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
- this(bounds, new int[]{paddingLeft, paddingTop, paddingRight, paddingBottom});
- }
-
- public LatLngBounds getBounds() {
- return bounds;
- }
-
- public RectF getPadding() {
- return padding;
- }
-
- @Override
- public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
- // Get required objects
- Projection projection = mapboxMap.getProjection();
- UiSettings uiSettings = mapboxMap.getUiSettings();
-
- // calculate correct padding
- int[] mapPadding = mapboxMap.getPadding();
- RectF latLngPadding = getPadding();
- RectF padding = new RectF(latLngPadding.left + mapPadding[0],
- latLngPadding.top + mapPadding[1],
- latLngPadding.right + mapPadding[2],
- latLngPadding.bottom + mapPadding[3]);
-
- // Calculate the bounds of the possibly rotated shape with respect to the viewport
- PointF nePixel = new PointF(-Float.MAX_VALUE, -Float.MAX_VALUE);
- PointF swPixel = new PointF(Float.MAX_VALUE, Float.MAX_VALUE);
- float viewportHeight = uiSettings.getHeight();
- for (LatLng latLng : getBounds().toLatLngs()) {
- PointF pixel = projection.toScreenLocation(latLng);
- swPixel.x = Math.min(swPixel.x, pixel.x);
- nePixel.x = Math.max(nePixel.x, pixel.x);
- swPixel.y = Math.min(swPixel.y, viewportHeight - pixel.y);
- nePixel.y = Math.max(nePixel.y, viewportHeight - pixel.y);
- }
-
- // Calculate width/height
- float width = nePixel.x - swPixel.x;
- float height = nePixel.y - swPixel.y;
-
- double zoom = 0;
- float minScale = 1;
- // Calculate the zoom level
- if (padding != null) {
- float scaleX = (uiSettings.getWidth() - padding.left - padding.right) / width;
- float scaleY = (uiSettings.getHeight() - padding.top - padding.bottom) / height;
- minScale = scaleX < scaleY ? scaleX : scaleY;
- zoom = projection.calculateZoom(minScale);
- zoom = MathUtils.clamp(zoom, (float) mapboxMap.getMinZoom(), (float) mapboxMap.getMaxZoom());
- }
-
- // Calculate the center point
- PointF paddedNEPixel = new PointF(nePixel.x + padding.right / minScale, nePixel.y + padding.top / minScale);
- PointF paddedSWPixel = new PointF(swPixel.x - padding.left / minScale, swPixel.y - padding.bottom / minScale);
- PointF centerPixel = new PointF((paddedNEPixel.x + paddedSWPixel.x) / 2, (paddedNEPixel.y + paddedSWPixel.y) / 2);
- centerPixel.y = viewportHeight - centerPixel.y;
- LatLng center = projection.fromScreenLocation(centerPixel);
-
- return new CameraPosition.Builder()
- .target(center)
- .zoom((float) zoom)
- .tilt(0)
- .bearing(0)
- .build();
- }
+ public float getY() {
+ return y;
}
- static final class CameraMoveUpdate implements CameraUpdate {
-
- private float x;
- private float y;
-
- CameraMoveUpdate(float x, float y) {
- this.x = x;
- this.y = y;
- }
-
- @Override
- public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
- UiSettings uiSettings = mapboxMap.getUiSettings();
- Projection projection = mapboxMap.getProjection();
-
- // Calculate the new center point
- float viewPortWidth = uiSettings.getWidth();
- float viewPortHeight = uiSettings.getHeight();
- PointF targetPoint = new PointF(viewPortWidth / 2 + x, viewPortHeight / 2 + y);
-
- // Convert point to LatLng
- LatLng latLng = projection.fromScreenLocation(targetPoint);
-
- CameraPosition previousPosition = mapboxMap.getCameraPosition();
- return new CameraPosition.Builder()
- .target(latLng != null ? latLng : previousPosition.target)
- .zoom(previousPosition.zoom)
- .tilt(previousPosition.tilt)
- .bearing(previousPosition.bearing)
- .build();
- }
+ double transformZoom(double currentZoom) {
+ switch (getType()) {
+ case CameraUpdateFactory.ZoomUpdate.ZOOM_IN:
+ currentZoom++;
+ break;
+ case CameraUpdateFactory.ZoomUpdate.ZOOM_OUT:
+ currentZoom--;
+ if (currentZoom < 0) {
+ currentZoom = 0;
+ }
+ break;
+ case CameraUpdateFactory.ZoomUpdate.ZOOM_TO:
+ currentZoom = getZoom();
+ break;
+ case CameraUpdateFactory.ZoomUpdate.ZOOM_BY:
+ currentZoom = currentZoom + getZoom();
+ break;
+ case CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT:
+ currentZoom = currentZoom + getZoom();
+ break;
+ }
+ return currentZoom;
}
- static final class ZoomUpdate implements CameraUpdate {
-
- @IntDef({ZOOM_IN, ZOOM_OUT, ZOOM_BY, ZOOM_TO, ZOOM_TO_POINT})
- @Retention(RetentionPolicy.SOURCE)
- @interface Type {
- }
-
- static final int ZOOM_IN = 0;
- static final int ZOOM_OUT = 1;
- static final int ZOOM_BY = 2;
- static final int ZOOM_TO = 3;
- static final int ZOOM_TO_POINT = 4;
-
- @Type
- private final int type;
- private final double zoom;
- private float x;
- private float y;
-
- ZoomUpdate(@Type int type) {
- this.type = type;
- this.zoom = 0;
- }
-
- ZoomUpdate(@Type int type, float zoom) {
- this.type = type;
- this.zoom = zoom;
- }
-
- ZoomUpdate(float zoom, float x, float y) {
- this.type = ZOOM_TO_POINT;
- this.zoom = zoom;
- this.x = x;
- this.y = y;
- }
-
- public double getZoom() {
- return zoom;
- }
-
- @Type
- public int getType() {
- return type;
- }
-
- public float getX() {
- return x;
- }
-
- public float getY() {
- return y;
- }
-
- double transformZoom(double currentZoom) {
- switch (getType()) {
- case CameraUpdateFactory.ZoomUpdate.ZOOM_IN:
- currentZoom++;
- break;
- case CameraUpdateFactory.ZoomUpdate.ZOOM_OUT:
- currentZoom--;
- if (currentZoom < 0) {
- currentZoom = 0;
- }
- break;
- case CameraUpdateFactory.ZoomUpdate.ZOOM_TO:
- currentZoom = getZoom();
- break;
- case CameraUpdateFactory.ZoomUpdate.ZOOM_BY:
- currentZoom = currentZoom + getZoom();
- break;
- case CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT:
- currentZoom = currentZoom + getZoom();
- break;
- }
- return currentZoom;
- }
-
- @Override
- public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- if (getType() != CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT) {
- return new CameraPosition.Builder(cameraPosition)
- .zoom(transformZoom(cameraPosition.zoom))
- .build();
- } else {
- return new CameraPosition.Builder(cameraPosition)
- .zoom(transformZoom(cameraPosition.zoom))
- .target(mapboxMap.getProjection().fromScreenLocation(new PointF(getX(), getY())))
- .build();
- }
- }
+ @Override
+ public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ if (getType() != CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT) {
+ return new CameraPosition.Builder(cameraPosition)
+ .zoom(transformZoom(cameraPosition.zoom))
+ .build();
+ } else {
+ return new CameraPosition.Builder(cameraPosition)
+ .zoom(transformZoom(cameraPosition.zoom))
+ .target(mapboxMap.getProjection().fromScreenLocation(new PointF(getX(), getY())))
+ .build();
+ }
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeoConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeoConstants.java
index ed6f77f419..009ae936d5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeoConstants.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeoConstants.java
@@ -5,34 +5,34 @@ package com.mapbox.mapboxsdk.constants;
*/
public class GeoConstants {
- /**
- * The <a href='http://en.wikipedia.org/wiki/Earth_radius#Equatorial_radius'>equatorial radius</a>
- * value in meters
- */
- public static final int RADIUS_EARTH_METERS = 6378137;
+ /**
+ * The <a href='http://en.wikipedia.org/wiki/Earth_radius#Equatorial_radius'>equatorial radius</a>
+ * value in meters
+ */
+ public static final int RADIUS_EARTH_METERS = 6378137;
- /**
- * The minimum latitude on Earth. This is the minimum latitude representable
- * by Mapbox GL's Mercator projection, because the projection distorts latitude
- * near the poles towards infinity.
- */
- public static final double MIN_LATITUDE = -85.05112878;
+ /**
+ * The minimum latitude on Earth. This is the minimum latitude representable
+ * by Mapbox GL's Mercator projection, because the projection distorts latitude
+ * near the poles towards infinity.
+ */
+ public static final double MIN_LATITUDE = -85.05112878;
- /**
- * The maximum latitude on Earth. This is the maximum latitude representable
- * by Mapbox GL's Mercator projection, because the projection distorts latitude
- * near the poles towards infinity.
- */
- public static final double MAX_LATITUDE = 85.05112878;
+ /**
+ * The maximum latitude on Earth. This is the maximum latitude representable
+ * by Mapbox GL's Mercator projection, because the projection distorts latitude
+ * near the poles towards infinity.
+ */
+ public static final double MAX_LATITUDE = 85.05112878;
- /**
- * The minimum longitude on Earth
- */
- public static final double MIN_LONGITUDE = -180;
+ /**
+ * The minimum longitude on Earth
+ */
+ public static final double MIN_LONGITUDE = -180;
- /**
- * The maximum longitude on Earth
- */
- public static final double MAX_LONGITUDE = 180;
+ /**
+ * The maximum longitude on Earth
+ */
+ public static final double MAX_LONGITUDE = 180;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
index 10d5c55044..fbf307541b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
@@ -1,6 +1,5 @@
package com.mapbox.mapboxsdk.constants;
-import android.content.Context;
import java.util.Locale;
/**
@@ -8,132 +7,144 @@ import java.util.Locale;
*/
public class MapboxConstants {
- /**
- * Default Locale for data processing (ex: String.toLowerCase(MAPBOX_LOCALE, "foo"))
- */
- public static final Locale MAPBOX_LOCALE = Locale.US;
-
- /**
- * Key used to store access token in AndroidManifest.xml
- * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)}
- */
- @Deprecated
- public static final String KEY_META_DATA_MANIFEST = "com.mapbox.AccessToken";
-
- /**
- * Key used to store staging data server url in AndroidManifest.xml
- */
- public static final String KEY_META_DATA_STAGING_SERVER = "com.mapbox.TestEventsServer";
-
- /**
- * Key used to store staging data server access token in AndroidManifest.xml
- */
- public static final String KEY_META_DATA_STAGING_ACCESS_TOKEN = "com.mapbox.TestEventsAccessToken";
-
- /**
- * Key used to switch storage to external in AndroidManifest.xml
- */
- public final static String KEY_META_DATA_SET_STORAGE_EXTERNAL = "com.mapbox.SetStorageExternal";
-
- /**
- * Default value for KEY_META_DATA_SET_STORAGE_EXTERNAL (default is internal storage)
- */
- public final static boolean DEFAULT_SET_STORAGE_EXTERNAL = false;
-
- /**
- * Unmeasured state
- */
- public final static float UNMEASURED = -1f;
-
- /**
- * Default animation time
- */
- public static final int ANIMATION_DURATION = 300;
-
- /**
- * Default short animation time
- */
- public static final int ANIMATION_DURATION_SHORT = 150;
-
- /**
- * The currently supported minimum zoom level.
- */
- public static final float MINIMUM_ZOOM = 0.0f;
-
- /**
- * The currently supported maximum zoom level.
- */
- public static final float MAXIMUM_ZOOM = 21.0f;
-
- /**
- * The currently supported maximum tilt value.
- */
- public static final double MAXIMUM_TILT = 60;
-
- /**
- * The currently supported minimum tilt value.
- */
- public static final double MINIMUM_TILT = 0;
-
- /**
- * The currently supported maximum direction
- */
- public static final double MAXIMUM_DIRECTION = 360;
-
- /**
- * The currently supported minimum direction
- */
- public static final double MINIMUM_DIRECTION = 0;
-
- /**
- * Fragment Argument Key for MapboxMapOptions
- */
- public static final String FRAG_ARG_MAPBOXMAPOPTIONS = "MapboxMapOptions";
-
- // Save instance state keys
- public static final String STATE_HAS_SAVED_STATE = "savedState";
- public static final String STATE_CAMERA_POSITION = "cameraPosition";
- public static final String STATE_ZOOM_ENABLED = "zoomEnabled";
- public static final String STATE_ZOOM_ENABLED_CHANGE = "zoomEnabledChange";
- public static final String STATE_SCROLL_ENABLED = "scrollEnabled";
- public static final String STATE_SCROLL_ENABLED_CHANGE = "scrollEnabledChange";
- public static final String STATE_ROTATE_ENABLED = "rotateEnabled";
- public static final String STATE_ROTATE_ENABLED_CHANGE = "rotateEnabledChange";
- public static final String STATE_TILT_ENABLED = "tiltEnabled";
- public static final String STATE_TILT_ENABLED_CHANGE = "tiltEnabledChange";
- public static final String STATE_ZOOM_CONTROLS_ENABLED = "zoomControlsEnabled";
- public static final String STATE_DEBUG_ACTIVE = "debugActive";
- public static final String STATE_STYLE_URL = "styleUrl";
- public static final String STATE_MY_LOCATION_ENABLED = "myLocationEnabled";
- public static final String STATE_MY_LOCATION_TRACKING_MODE = "myLocationTracking";
- public static final String STATE_MY_BEARING_TRACKING_MODE = "myBearingTracking";
- public static final String STATE_MY_LOCATION_TRACKING_DISMISS = "myLocationTrackingDismiss";
- public static final String STATE_MY_BEARING_TRACKING_DISMISS = "myBearingTrackingDismiss";
- public static final String STATE_COMPASS_ENABLED = "compassEnabled";
- public static final String STATE_COMPASS_GRAVITY = "compassGravity";
- public static final String STATE_COMPASS_MARGIN_LEFT = "compassMarginLeft";
- public static final String STATE_COMPASS_MARGIN_TOP = "compassMarginTop";
- public static final String STATE_COMPASS_MARGIN_RIGHT = "compassMarginRight";
- public static final String STATE_COMPASS_MARGIN_BOTTOM = "compassMarginBottom";
- public static final String STATE_COMPASS_FADE_WHEN_FACING_NORTH = "compassFade";
- public static final String STATE_LOGO_GRAVITY = "logoGravity";
- public static final String STATE_LOGO_MARGIN_LEFT = "logoMarginLeft";
- public static final String STATE_LOGO_MARGIN_TOP = "logoMarginTop";
- public static final String STATE_LOGO_MARGIN_RIGHT = "logoMarginRight";
- public static final String STATE_LOGO_MARGIN_BOTTOM = "logoMarginBottom";
- public static final String STATE_LOGO_ENABLED = "logoEnabled";
- public static final String STATE_ATTRIBUTION_GRAVITY = "attrGravity";
- public static final String STATE_ATTRIBUTION_MARGIN_LEFT = "attrMarginLeft";
- public static final String STATE_ATTRIBUTION_MARGIN_TOP = "attrMarginTop";
- public static final String STATE_ATTRIBUTION_MARGIN_RIGHT = "attrMarginRight";
- public static final String STATE_ATTRIBUTION_MARGIN_BOTTOM = "atrrMarginBottom";
- public static final String STATE_ATTRIBUTION_ENABLED = "atrrEnabled";
-
- public static final String TAG = "MapboxMap";
-
- public static final String MAPBOX_SHARED_PREFERENCES_FILE = "MapboxSharedPreferences";
- public static final String MAPBOX_SHARED_PREFERENCE_KEY_VENDORID = "mapboxVendorId";
- public static final String MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED = "mapboxTelemetryEnabled";
- public static final String MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_URL = "mapboxTelemetryStagingUrl";
- public static final String MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_ACCESS_TOKEN = "mapboxTelemetryStagingAccessToken";
+ /**
+ * Default Locale for data processing (ex: String.toLowerCase(MAPBOX_LOCALE, "foo"))
+ */
+ public static final Locale MAPBOX_LOCALE = Locale.US;
+
+ /**
+ * Key used to store staging data server url in AndroidManifest.xml
+ */
+ public static final String KEY_META_DATA_STAGING_SERVER = "com.mapbox.TestEventsServer";
+
+ /**
+ * Key used to store staging data server access token in AndroidManifest.xml
+ */
+ public static final String KEY_META_DATA_STAGING_ACCESS_TOKEN = "com.mapbox.TestEventsAccessToken";
+
+ /**
+ * Key used to switch storage to external in AndroidManifest.xml
+ */
+ public static final String KEY_META_DATA_SET_STORAGE_EXTERNAL = "com.mapbox.SetStorageExternal";
+
+ /**
+ * Default value for KEY_META_DATA_SET_STORAGE_EXTERNAL (default is internal storage)
+ */
+ public static final boolean DEFAULT_SET_STORAGE_EXTERNAL = false;
+
+ /**
+ * Unmeasured state
+ */
+ public static final float UNMEASURED = -1f;
+
+ /**
+ * Default animation time
+ */
+ public static final int ANIMATION_DURATION = 300;
+
+ /**
+ * Default short animation time
+ */
+ public static final int ANIMATION_DURATION_SHORT = 150;
+
+ /**
+ * Animation time of a fling gesture
+ */
+ public static final long ANIMATION_DURATION_FLING_BASE = ANIMATION_DURATION_SHORT;
+
+ /**
+ * Velocity threshold for a fling gesture
+ */
+ public static final long VELOCITY_THRESHOLD_IGNORE_FLING = 1000;
+
+ /**
+ * The currently supported minimum zoom level.
+ */
+ public static final float MINIMUM_ZOOM = 0.0f;
+
+ /**
+ * The currently supported maximum zoom level.
+ */
+ public static final float MAXIMUM_ZOOM = 20.0f;
+
+ /**
+ * The currently supported maximum tilt value.
+ */
+ public static final double MAXIMUM_TILT = 60;
+
+ /**
+ * The currently supported minimum tilt value.
+ */
+ public static final double MINIMUM_TILT = 0;
+
+ /**
+ * The currently supported maximum direction
+ */
+ public static final double MAXIMUM_DIRECTION = 360;
+
+ /**
+ * The currently supported minimum direction
+ */
+ public static final double MINIMUM_DIRECTION = 0;
+
+ /**
+ * The currently used minimun scale factor to clamp to when a quick zoom gesture occurs
+ */
+ public static final float MINIMUM_SCALE_FACTOR_CLAMP = 0.65f;
+
+ /**
+ * The currently used maximum scale factor to clamp to when a quick zoom gesture occurs
+ */
+ public static final float MAXIMUM_SCALE_FACTOR_CLAMP = 1.35f;
+
+ /**
+ * Fragment Argument Key for MapboxMapOptions
+ */
+ public static final String FRAG_ARG_MAPBOXMAPOPTIONS = "MapboxMapOptions";
+
+ // Save instance state keys
+ public static final String STATE_HAS_SAVED_STATE = "savedState";
+ public static final String STATE_CAMERA_POSITION = "cameraPosition";
+ public static final String STATE_ZOOM_ENABLED = "zoomEnabled";
+ public static final String STATE_ZOOM_ENABLED_CHANGE = "zoomEnabledChange";
+ public static final String STATE_SCROLL_ENABLED = "scrollEnabled";
+ public static final String STATE_SCROLL_ENABLED_CHANGE = "scrollEnabledChange";
+ public static final String STATE_ROTATE_ENABLED = "rotateEnabled";
+ public static final String STATE_ROTATE_ENABLED_CHANGE = "rotateEnabledChange";
+ public static final String STATE_TILT_ENABLED = "tiltEnabled";
+ public static final String STATE_TILT_ENABLED_CHANGE = "tiltEnabledChange";
+ public static final String STATE_ZOOM_CONTROLS_ENABLED = "zoomControlsEnabled";
+ public static final String STATE_DEBUG_ACTIVE = "debugActive";
+ public static final String STATE_STYLE_URL = "styleUrl";
+ public static final String STATE_MY_LOCATION_ENABLED = "myLocationEnabled";
+ public static final String STATE_MY_LOCATION_TRACKING_MODE = "myLocationTracking";
+ public static final String STATE_MY_BEARING_TRACKING_MODE = "myBearingTracking";
+ public static final String STATE_MY_LOCATION_TRACKING_DISMISS = "myLocationTrackingDismiss";
+ public static final String STATE_MY_BEARING_TRACKING_DISMISS = "myBearingTrackingDismiss";
+ public static final String STATE_COMPASS_ENABLED = "compassEnabled";
+ public static final String STATE_COMPASS_GRAVITY = "compassGravity";
+ public static final String STATE_COMPASS_MARGIN_LEFT = "compassMarginLeft";
+ public static final String STATE_COMPASS_MARGIN_TOP = "compassMarginTop";
+ public static final String STATE_COMPASS_MARGIN_RIGHT = "compassMarginRight";
+ public static final String STATE_COMPASS_MARGIN_BOTTOM = "compassMarginBottom";
+ public static final String STATE_COMPASS_FADE_WHEN_FACING_NORTH = "compassFade";
+ public static final String STATE_LOGO_GRAVITY = "logoGravity";
+ public static final String STATE_LOGO_MARGIN_LEFT = "logoMarginLeft";
+ public static final String STATE_LOGO_MARGIN_TOP = "logoMarginTop";
+ public static final String STATE_LOGO_MARGIN_RIGHT = "logoMarginRight";
+ public static final String STATE_LOGO_MARGIN_BOTTOM = "logoMarginBottom";
+ public static final String STATE_LOGO_ENABLED = "logoEnabled";
+ public static final String STATE_ATTRIBUTION_GRAVITY = "attrGravity";
+ public static final String STATE_ATTRIBUTION_MARGIN_LEFT = "attrMarginLeft";
+ public static final String STATE_ATTRIBUTION_MARGIN_TOP = "attrMarginTop";
+ public static final String STATE_ATTRIBUTION_MARGIN_RIGHT = "attrMarginRight";
+ public static final String STATE_ATTRIBUTION_MARGIN_BOTTOM = "atrrMarginBottom";
+ public static final String STATE_ATTRIBUTION_ENABLED = "atrrEnabled";
+
+ public static final String MAPBOX_SHARED_PREFERENCES_FILE = "MapboxSharedPreferences";
+ public static final String MAPBOX_SHARED_PREFERENCE_KEY_VENDORID = "mapboxVendorId";
+ public static final String MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED = "mapboxTelemetryEnabled";
+ public static final String MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_URL = "mapboxTelemetryStagingUrl";
+ public static final String MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_ACCESS_TOKEN =
+ "mapboxTelemetryStagingAccessToken";
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java
index 929df2da77..cba2fb282c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java
@@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.constants;
import android.support.annotation.IntDef;
-import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
import java.lang.annotation.Retention;
@@ -11,34 +10,34 @@ import java.lang.annotation.RetentionPolicy;
/**
* MyBearingTracking exposes different types bearing tracking modes.
*
- * @see MapView#setMyBearingTrackingMode(int)
+ * @see com.mapbox.mapboxsdk.maps.TrackingSettings#setMyBearingTrackingMode(int)
* @see MyLocationView#setMyBearingTrackingMode(int)
*/
public class MyBearingTracking {
- /**
- * Indicates the parameter accepts one of the values from {@link MyBearingTracking}.
- */
- @IntDef({NONE, COMPASS, GPS, /**COMBINED**/})
- @Retention(RetentionPolicy.SOURCE)
- public @interface Mode {
- }
-
- /**
- * Bearing tracking is disabled
- */
- public static final int NONE = 0x00000000;
-
- /**
- * Tracking the bearing of the user based on sensor data
- */
- public static final int COMPASS = 0x00000004;
-
- /**
- * Tracking the bearing of the user based on GPS data
- */
- public static final int GPS = 0x00000008;
-
- //public static final int COMBINED = 0x00000012;
+ /**
+ * Indicates the parameter accepts one of the values from {@link MyBearingTracking}.
+ */
+ @IntDef( {NONE, COMPASS, GPS, /**COMBINED**/})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Mode {
+ }
+
+ /**
+ * Bearing tracking is disabled
+ */
+ public static final int NONE = 0x00000000;
+
+ /**
+ * Tracking the bearing of the user based on sensor data
+ */
+ public static final int COMPASS = 0x00000004;
+
+ /**
+ * Tracking the bearing of the user based on GPS data
+ */
+ public static final int GPS = 0x00000008;
+
+ //public static final int COMBINED = 0x00000012;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java
index b2a49c6454..d1eaac04de 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java
@@ -11,27 +11,27 @@ import java.lang.annotation.RetentionPolicy;
/**
* MyLocationTracking exposes different types of locational tracking modes.
*
- * @see MapView#setMyLocationTrackingMode(int)
+ * @see com.mapbox.mapboxsdk.maps.TrackingSettings#setMyLocationTrackingMode(int)
* @see MyLocationView#setMyLocationTrackingMode(int)
*/
public class MyLocationTracking {
- /**
- * Indicates the parameter accepts one of the values from {@link MyLocationTracking}.
- */
- @IntDef({TRACKING_NONE, TRACKING_FOLLOW})
- @Retention(RetentionPolicy.SOURCE)
- public @interface Mode {
- }
-
- /**
- * Location tracking is disabled.
- */
- public static final int TRACKING_NONE = 0x00000000;
-
- /**
- * Tracking the location of the user, {@link MapView} will reposition to center of {@link MyLocationView}
- */
- public static final int TRACKING_FOLLOW = 0x00000004;
+ /**
+ * Indicates the parameter accepts one of the values from {@link MyLocationTracking}.
+ */
+ @IntDef( {TRACKING_NONE, TRACKING_FOLLOW})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Mode {
+ }
+
+ /**
+ * Location tracking is disabled.
+ */
+ public static final int TRACKING_NONE = 0x00000000;
+
+ /**
+ * Tracking the location of the user, {@link MapView} will reposition to center of {@link MyLocationView}
+ */
+ public static final int TRACKING_FOLLOW = 0x00000004;
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java
index 51eb038052..574ef4afa6 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java
@@ -18,61 +18,61 @@ import java.lang.annotation.RetentionPolicy;
public class Style {
- /**
- * Indicates the parameter accepts one of the values from {@link Style}. Using one of these
- * constants means your map style will always use the latest version and may change as we
- * improve the style
- */
- @StringDef({MAPBOX_STREETS, OUTDOORS, EMERALD, LIGHT, DARK, SATELLITE, SATELLITE_STREETS})
- @Retention(RetentionPolicy.SOURCE)
- public @interface StyleUrl {
- }
+ /**
+ * Indicates the parameter accepts one of the values from {@link Style}. Using one of these
+ * constants means your map style will always use the latest version and may change as we
+ * improve the style
+ */
+ @StringDef( {MAPBOX_STREETS, OUTDOORS, EMERALD, LIGHT, DARK, SATELLITE, SATELLITE_STREETS})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StyleUrl {
+ }
- // IMPORTANT: If you change any of these you also need to edit them in strings.xml
+ // IMPORTANT: If you change any of these you also need to edit them in strings.xml
- /**
- * Mapbox Streets: A complete basemap, perfect for incorporating your own data. Using this
- * constant means your map style will always use the latest version and may change as we
- * improve the style.
- */
- public static final String MAPBOX_STREETS = "mapbox://styles/mapbox/streets-v9";
+ /**
+ * Mapbox Streets: A complete basemap, perfect for incorporating your own data. Using this
+ * constant means your map style will always use the latest version and may change as we
+ * improve the style.
+ */
+ public static final String MAPBOX_STREETS = "mapbox://styles/mapbox/streets-v9";
- /**
- * Outdoors: A general-purpose style tailored to outdoor activities. Using this constant means
- * your map style will always use the latest version and may change as we improve the style.
- */
- public static final String OUTDOORS = "mapbox://styles/mapbox/outdoors-v9";
+ /**
+ * Outdoors: A general-purpose style tailored to outdoor activities. Using this constant means
+ * your map style will always use the latest version and may change as we improve the style.
+ */
+ public static final String OUTDOORS = "mapbox://styles/mapbox/outdoors-v9";
- /**
- * Emerald: A versatile style, with emphasis on road networks and public transit.
- *
- * @deprecated this style has been deprecated and will be removed in future versions.
- */
- @Deprecated
- public static final String EMERALD = "mapbox://styles/mapbox/emerald-v8";
+ /**
+ * Emerald: A versatile style, with emphasis on road networks and public transit.
+ *
+ * @deprecated this style has been deprecated and will be removed in future versions.
+ */
+ @Deprecated
+ public static final String EMERALD = "mapbox://styles/mapbox/emerald-v8";
- /**
- * Light: Subtle light backdrop for data visualizations. Using this constant means your map
- * style will always use the latest version and may change as we improve the style.
- */
- public static final String LIGHT = "mapbox://styles/mapbox/light-v9";
+ /**
+ * Light: Subtle light backdrop for data visualizations. Using this constant means your map
+ * style will always use the latest version and may change as we improve the style.
+ */
+ public static final String LIGHT = "mapbox://styles/mapbox/light-v9";
- /**
- * Dark: Subtle dark backdrop for data visualizations. Using this constant means your map style
- * will always use the latest version and may change as we improve the style.
- */
- public static final String DARK = "mapbox://styles/mapbox/dark-v9";
+ /**
+ * Dark: Subtle dark backdrop for data visualizations. Using this constant means your map style
+ * will always use the latest version and may change as we improve the style.
+ */
+ public static final String DARK = "mapbox://styles/mapbox/dark-v9";
- /**
- * Satellite: A beautiful global satellite and aerial imagery layer. Using this constant means
- * your map style will always use the latest version and may change as we improve the style.
- */
- public static final String SATELLITE = "mapbox://styles/mapbox/satellite-v9";
+ /**
+ * Satellite: A beautiful global satellite and aerial imagery layer. Using this constant means
+ * your map style will always use the latest version and may change as we improve the style.
+ */
+ public static final String SATELLITE = "mapbox://styles/mapbox/satellite-v9";
- /**
- * Satellite Streets: Global satellite and aerial imagery with unobtrusive labels. Using this
- * constant means your map style will always use the latest version and may change as we
- * improve the style.
- */
- public static final String SATELLITE_STREETS = "mapbox://styles/mapbox/satellite-streets-v9";
+ /**
+ * Satellite Streets: Global satellite and aerial imagery with unobtrusive labels. Using this
+ * constant means your map style will always use the latest version and may change as we
+ * improve the style.
+ */
+ public static final String SATELLITE_STREETS = "mapbox://styles/mapbox/satellite-streets-v9";
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/ConversionException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/ConversionException.java
index 87656db2a9..be2b586683 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/ConversionException.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/ConversionException.java
@@ -5,18 +5,18 @@ package com.mapbox.mapboxsdk.exceptions;
*/
public class ConversionException extends RuntimeException {
- public ConversionException() {
- }
+ public ConversionException() {
+ }
- public ConversionException(String detailMessage) {
- super(detailMessage);
- }
+ public ConversionException(String detailMessage) {
+ super(detailMessage);
+ }
- public ConversionException(String detailMessage, Throwable throwable) {
- super(detailMessage, throwable);
- }
+ public ConversionException(String detailMessage, Throwable throwable) {
+ super(detailMessage, throwable);
+ }
- public ConversionException(Throwable throwable) {
- super(throwable);
- }
+ public ConversionException(Throwable throwable) {
+ super(throwable);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java
index 1be82d6178..7154049bd7 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java
@@ -19,9 +19,9 @@ import com.mapbox.mapboxsdk.maps.MapView;
*/
public class IconBitmapChangedException extends RuntimeException {
- public IconBitmapChangedException() {
- super("The added Marker has an Icon with a bitmap that has been modified. An Icon cannot be modified" +
- "after it has been added to the map in a Marker.");
- }
+ public IconBitmapChangedException() {
+ super("The added Marker has an Icon with a bitmap that has been modified. An Icon cannot be modified"
+ + "after it has been added to the map in a Marker.");
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java
index 77797ecb4f..95851fc1d2 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java
@@ -1,22 +1,24 @@
package com.mapbox.mapboxsdk.exceptions;
+import android.content.Context;
import android.os.Bundle;
import com.mapbox.mapboxsdk.maps.MapView;
/**
- * A {@code InvalidAccessTokenException} is thrown by {@link com.mapbox.mapboxsdk.maps.MapboxMap} when there is either no access
- * token set before {@link MapView#onCreate(Bundle)} or an invalid access token is set in {@link MapView#setAccessToken(String)}
+ * A {@code InvalidAccessTokenException} is thrown by {@link com.mapbox.mapboxsdk.maps.MapboxMap}
+ * when there is either no access token set before {@link MapView#onCreate(Bundle)} or an invalid access token
+ * is set in {@link com.mapbox.mapboxsdk.Mapbox#getInstance(Context, String)}
*
* @see MapView#onCreate(Bundle)
- * @see MapView#setAccessToken(String)
+ * @see com.mapbox.mapboxsdk.Mapbox#getInstance(Context, String)
*/
public class InvalidAccessTokenException extends RuntimeException {
- public InvalidAccessTokenException() {
- super("\nUsing MapView requires setting a valid access token. Use setAccessToken on Mapview to provide one. " +
- "\nPlease see https://www.mapbox.com/help/create-api-access-token/ to learn how to create one." +
- "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens.");
- }
-
+ public InvalidAccessTokenException() {
+ super("\nUsing MapView requires setting a valid access token. Use Mapbox.getInstance(Context context, "
+ + "String accessToken) to provide one. "
+ + "\nPlease see https://www.mapbox.com/help/create-api-access-token/ to learn how to create one."
+ + "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens.");
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidLatLngBoundsException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidLatLngBoundsException.java
index 92feaac64b..08a23a7373 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidLatLngBoundsException.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidLatLngBoundsException.java
@@ -6,7 +6,7 @@ package com.mapbox.mapboxsdk.exceptions;
*/
public class InvalidLatLngBoundsException extends RuntimeException {
- public InvalidLatLngBoundsException(int latLngsListSize) {
- super("Cannot create a LatLngBounds from " + latLngsListSize + " items");
- }
+ public InvalidLatLngBoundsException(int latLngsListSize) {
+ super("Cannot create a LatLngBounds from " + latLngsListSize + " items");
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidMarkerPositionException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidMarkerPositionException.java
index 8dc98118b1..e5a647841f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidMarkerPositionException.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidMarkerPositionException.java
@@ -2,9 +2,9 @@ package com.mapbox.mapboxsdk.exceptions;
public class InvalidMarkerPositionException extends RuntimeException {
- public InvalidMarkerPositionException() {
- super("Adding an invalid Marker to a Map. " +
- "Missing the required position field. " +
- "Provide a non null LatLng as position to the Marker.");
- }
+ public InvalidMarkerPositionException() {
+ super("Adding an invalid Marker to a Map. "
+ + "Missing the required position field. "
+ + "Provide a non null LatLng as position to the Marker.");
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/MapboxAccountManagerNotStartedException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/MapboxAccountManagerNotStartedException.java
deleted file mode 100644
index 4954098f15..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/MapboxAccountManagerNotStartedException.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.mapbox.mapboxsdk.exceptions;
-
-
-import android.content.Context;
-import android.os.Bundle;
-
-import com.mapbox.mapboxsdk.MapboxAccountManager;
-import com.mapbox.mapboxsdk.maps.MapView;
-
-/**
- * A MapboxAccountManagerNotStartedException is thrown by {@link com.mapbox.mapboxsdk.maps.MapView}
- * when {@link MapboxAccountManager} is not started before {@link MapView#onCreate(Bundle)}.
- *
- * @see MapView#onCreate(Bundle)
- * @see MapboxAccountManager#start(Context, String)
- */
-public class MapboxAccountManagerNotStartedException extends RuntimeException {
-
- public MapboxAccountManagerNotStartedException() {
- super("\nMapboxAccountManager was not started correctly. Use MapboxAccountManager#start(Context, String) to initialise. " +
- "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens.");
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TelemetryServiceNotConfiguredException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TelemetryServiceNotConfiguredException.java
index ec2b0d792d..e2e114fa77 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TelemetryServiceNotConfiguredException.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TelemetryServiceNotConfiguredException.java
@@ -12,10 +12,11 @@ import com.mapbox.mapboxsdk.maps.MapView;
*/
public class TelemetryServiceNotConfiguredException extends RuntimeException {
- public TelemetryServiceNotConfiguredException() {
- super("\nTelemetryService is not configured in your applications AndroidManifest.xml. " +
- "\nPlease add \"com.mapbox.mapboxsdk.telemetry.TelemetryService\" service in your applications AndroidManifest.xml" +
- "\nFor an example visit http://goo.gl/cET0Jn. For more information visit https://www.mapbox.com/android-sdk/.");
- }
+ public TelemetryServiceNotConfiguredException() {
+ super("\nTelemetryService is not configured in your applications AndroidManifest.xml. "
+ + "\nPlease add \"com.mapbox.mapboxsdk.telemetry.TelemetryService\" service in your applications "
+ + "AndroidManifest.xml"
+ + "\nFor an example visit http://goo.gl/cET0Jn. For more information visit https://www.mapbox.com/android-sdk/.");
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TooManyIconsException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TooManyIconsException.java
index 4dcdea112c..8923d822f2 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TooManyIconsException.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TooManyIconsException.java
@@ -14,8 +14,8 @@ import com.mapbox.mapboxsdk.annotations.IconFactory;
*/
public class TooManyIconsException extends RuntimeException {
- public TooManyIconsException() {
- super("Cannot create an Icon because there are already too many. Try reusing Icon objects whenever possible.");
- }
+ public TooManyIconsException() {
+ super("Cannot create an Icon because there are already too many. Try reusing Icon objects whenever possible.");
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ILatLng.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ILatLng.java
index afd22e5ddb..1af8e7cfc7 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ILatLng.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ILatLng.java
@@ -4,9 +4,9 @@ package com.mapbox.mapboxsdk.geometry;
* Describes a latitude, longitude point.
*/
public interface ILatLng {
- double getLatitude();
+ double getLatitude();
- double getLongitude();
+ double getLongitude();
- double getAltitude();
+ double getAltitude();
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/IProjectedMeters.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/IProjectedMeters.java
index 43fe25f8e5..694c935143 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/IProjectedMeters.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/IProjectedMeters.java
@@ -4,7 +4,7 @@ package com.mapbox.mapboxsdk.geometry;
* Describes a projection in Mercator meters.
*/
public interface IProjectedMeters {
- double getNorthing();
+ double getNorthing();
- double getEasting();
+ double getEasting();
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java
index 4449a7fe0d..b18b7e87b0 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java
@@ -21,183 +21,191 @@ import com.mapbox.mapboxsdk.utils.MathUtils;
*/
public class LatLng implements ILatLng, Parcelable {
- public static final Parcelable.Creator<LatLng> CREATOR = new Parcelable.Creator<LatLng>() {
- public LatLng createFromParcel(Parcel in) {
- return new LatLng(in);
- }
-
- public LatLng[] newArray(int size) {
- return new LatLng[size];
- }
- };
-
- private double latitude;
- private double longitude;
- private double altitude = 0.0;
-
- /**
- * Construct a new latitude, longitude point at (0, 0)
- */
- public LatLng() {
- this.latitude = 0.0;
- this.longitude = 0.0;
- }
-
- /**
- * Construct a new latitude, longitude point given float arguments
- * @param latitude Latitude in degrees
- * @param longitude Longitude in degrees
- */
- public LatLng(double latitude, double longitude) {
- this.latitude = latitude;
- this.longitude = longitude;
- }
-
- /**
- * Construct a new latitude, longitude, altitude point given float arguments
- * @param latitude Latitude in degrees
- * @param longitude Longitude in degress
- * @param altitude Altitude in meters
- */
- public LatLng(double latitude, double longitude, double altitude) {
- this.latitude = latitude;
- this.longitude = longitude;
- this.altitude = altitude;
- }
-
- /**
- * Transform a Location into a LatLng point
- * @param location Android Location
- */
- public LatLng(Location location) {
- this(location.getLatitude(), location.getLongitude(), location.getAltitude());
- }
-
- /**
- * Clone an existing latitude longitude point
- * @param aLatLng LatLng
- */
- public LatLng(LatLng aLatLng) {
- this.latitude = aLatLng.latitude;
- this.longitude = aLatLng.longitude;
- this.altitude = aLatLng.altitude;
- }
-
- protected LatLng(Parcel in) {
- latitude = in.readDouble();
- longitude = in.readDouble();
- altitude = in.readDouble();
- }
-
- public void setLatitude(double latitude) {
- this.latitude = latitude;
- }
-
- @Override
- public double getLatitude() {
- return latitude;
- }
-
- public void setLongitude(double longitude) {
- this.longitude = longitude;
- }
-
- @Override
- public double getLongitude() {
- return longitude;
- }
-
- public void setAltitude(double altitude) {
- this.altitude = altitude;
- }
-
- @Override
- public double getAltitude() {
- return altitude;
- }
-
- /**
- * Return a new LatLng object with a wrapped Longitude. This allows original data object
- * to remain unchanged.
- * @return New LatLng object with wrapped Longitude
- */
- public LatLng wrap(){
- LatLng wrappedVersion = new LatLng(this);
- double lon = wrappedVersion.getLongitude();
- if (lon < GeoConstants.MIN_LONGITUDE || lon > GeoConstants.MAX_LONGITUDE) {
- wrappedVersion.setLongitude(MathUtils.wrap(wrappedVersion.getLongitude(), GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE));
- }
- return wrappedVersion;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- LatLng latLng = (LatLng) o;
-
- return Double.compare(latLng.altitude, altitude) == 0 && Double.compare(latLng.latitude, latitude) == 0 && Double.compare(latLng.longitude, longitude) == 0;
- }
-
- @Override
- public int hashCode() {
- int result;
- long temp;
- temp = Double.doubleToLongBits(latitude);
- result = (int) (temp ^ (temp >>> 32));
- temp = Double.doubleToLongBits(longitude);
- result = 31 * result + (int) (temp ^ (temp >>> 32));
- temp = Double.doubleToLongBits(altitude);
- result = 31 * result + (int) (temp ^ (temp >>> 32));
- return result;
- }
-
- @Override
- public String toString() {
- return "LatLng [latitude=" + latitude + ", longitude=" + longitude + ", altitude=" + altitude + "]";
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeDouble(latitude);
- out.writeDouble(longitude);
- out.writeDouble(altitude);
- }
-
- /**
- * Calculate distance between two points
- * @param other Other LatLng to compare to
- * @return distance in meters
- */
- public double distanceTo(LatLng other) {
- if(latitude == other.latitude && longitude == other.longitude){
- // return 0.0 to avoid a NaN
- return 0.0;
- }
-
- final double a1 = Math.toRadians(this.latitude);
- final double a2 = Math.toRadians(this.longitude);
- final double b1 = Math.toRadians(other.getLatitude());
- final double b2 = Math.toRadians(other.getLongitude());
-
- final double cosa1 = Math.cos(a1);
- final double cosb1 = Math.cos(b1);
-
- final double t1 = cosa1 * Math.cos(a2) * cosb1 * Math.cos(b2);
- final double t2 = cosa1 * Math.sin(a2) * cosb1 * Math.sin(b2);
- final double t3 = Math.sin(a1) * Math.sin(b1);
- final double tt = Math.acos(t1 + t2 + t3);
-
- return GeoConstants.RADIUS_EARTH_METERS * tt;
- }
+ public static final Parcelable.Creator<LatLng> CREATOR = new Parcelable.Creator<LatLng>() {
+ public LatLng createFromParcel(Parcel in) {
+ return new LatLng(in);
+ }
+
+ public LatLng[] newArray(int size) {
+ return new LatLng[size];
+ }
+ };
+
+ private double latitude;
+ private double longitude;
+ private double altitude = 0.0;
+
+ /**
+ * Construct a new latitude, longitude point at (0, 0)
+ */
+ public LatLng() {
+ this.latitude = 0.0;
+ this.longitude = 0.0;
+ }
+
+ /**
+ * Construct a new latitude, longitude point given float arguments
+ *
+ * @param latitude Latitude in degrees
+ * @param longitude Longitude in degrees
+ */
+ public LatLng(double latitude, double longitude) {
+ this.latitude = latitude;
+ this.longitude = longitude;
+ }
+
+ /**
+ * Construct a new latitude, longitude, altitude point given float arguments
+ *
+ * @param latitude Latitude in degrees
+ * @param longitude Longitude in degress
+ * @param altitude Altitude in meters
+ */
+ public LatLng(double latitude, double longitude, double altitude) {
+ this.latitude = latitude;
+ this.longitude = longitude;
+ this.altitude = altitude;
+ }
+
+ /**
+ * Transform a Location into a LatLng point
+ *
+ * @param location Android Location
+ */
+ public LatLng(Location location) {
+ this(location.getLatitude(), location.getLongitude(), location.getAltitude());
+ }
+
+ /**
+ * Clone an existing latitude longitude point
+ *
+ * @param aLatLng LatLng
+ */
+ public LatLng(LatLng aLatLng) {
+ this.latitude = aLatLng.latitude;
+ this.longitude = aLatLng.longitude;
+ this.altitude = aLatLng.altitude;
+ }
+
+ protected LatLng(Parcel in) {
+ latitude = in.readDouble();
+ longitude = in.readDouble();
+ altitude = in.readDouble();
+ }
+
+ public void setLatitude(double latitude) {
+ this.latitude = latitude;
+ }
+
+ @Override
+ public double getLatitude() {
+ return latitude;
+ }
+
+ public void setLongitude(double longitude) {
+ this.longitude = longitude;
+ }
+
+ @Override
+ public double getLongitude() {
+ return longitude;
+ }
+
+ public void setAltitude(double altitude) {
+ this.altitude = altitude;
+ }
+
+ @Override
+ public double getAltitude() {
+ return altitude;
+ }
+
+ /**
+ * Return a new LatLng object with a wrapped Longitude. This allows original data object
+ * to remain unchanged.
+ *
+ * @return New LatLng object with wrapped Longitude
+ */
+ public LatLng wrap() {
+ LatLng wrappedVersion = new LatLng(this);
+ double lon = wrappedVersion.getLongitude();
+ if (lon < GeoConstants.MIN_LONGITUDE || lon > GeoConstants.MAX_LONGITUDE) {
+ wrappedVersion.setLongitude(MathUtils.wrap(wrappedVersion.getLongitude(), GeoConstants.MIN_LONGITUDE,
+ GeoConstants.MAX_LONGITUDE));
+ }
+ return wrappedVersion;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object == null || getClass() != object.getClass()) {
+ return false;
+ }
+
+ LatLng latLng = (LatLng) object;
+
+ return Double.compare(latLng.altitude, altitude) == 0 && Double.compare(latLng.latitude, latitude) == 0
+ && Double.compare(latLng.longitude, longitude) == 0;
+ }
+
+ @Override
+ public int hashCode() {
+ int result;
+ long temp;
+ temp = Double.doubleToLongBits(latitude);
+ result = (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(longitude);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(altitude);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "LatLng [latitude=" + latitude + ", longitude=" + longitude + ", altitude=" + altitude + "]";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeDouble(latitude);
+ out.writeDouble(longitude);
+ out.writeDouble(altitude);
+ }
+
+ /**
+ * Calculate distance between two points
+ *
+ * @param other Other LatLng to compare to
+ * @return distance in meters
+ */
+ public double distanceTo(LatLng other) {
+ if (latitude == other.latitude && longitude == other.longitude) {
+ // return 0.0 to avoid a NaN
+ return 0.0;
+ }
+
+ final double a1 = Math.toRadians(this.latitude);
+ final double a2 = Math.toRadians(this.longitude);
+ final double b1 = Math.toRadians(other.getLatitude());
+ final double b2 = Math.toRadians(other.getLongitude());
+
+ final double cosa1 = Math.cos(a1);
+ final double cosb1 = Math.cos(b1);
+
+ final double t1 = cosa1 * Math.cos(a2) * cosb1 * Math.cos(b2);
+ final double t2 = cosa1 * Math.sin(a2) * cosb1 * Math.sin(b2);
+ final double t3 = Math.sin(a1) * Math.sin(b1);
+ final double tt = Math.acos(t1 + t2 + t3);
+
+ return GeoConstants.RADIUS_EARTH_METERS * tt;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java
index 2fd28202af..3b92f0f0f5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java
@@ -14,292 +14,296 @@ import java.util.List;
*/
public class LatLngBounds implements Parcelable {
- private final double mLatNorth;
- private final double mLatSouth;
- private final double mLonEast;
- private final double mLonWest;
-
- /**
- * Construct a new LatLngBounds based on its corners, given in NESW
- * order.
- *
- * @param northLatitude Northern Latitude
- * @param eastLongitude Eastern Longitude
- * @param southLatitude Southern Latitude
- * @param westLongitude Western Longitude
- */
- LatLngBounds(final double northLatitude, final double eastLongitude, final double southLatitude, final double westLongitude) {
- this.mLatNorth = northLatitude;
- this.mLonEast = eastLongitude;
- this.mLatSouth = southLatitude;
- this.mLonWest = westLongitude;
+ private final double mLatNorth;
+ private final double mLatSouth;
+ private final double mLonEast;
+ private final double mLonWest;
+
+ /**
+ * Construct a new LatLngBounds based on its corners, given in NESW
+ * order.
+ *
+ * @param northLatitude Northern Latitude
+ * @param eastLongitude Eastern Longitude
+ * @param southLatitude Southern Latitude
+ * @param westLongitude Western Longitude
+ */
+ LatLngBounds(final double northLatitude, final double eastLongitude, final double southLatitude,
+ final double westLongitude) {
+ this.mLatNorth = northLatitude;
+ this.mLonEast = eastLongitude;
+ this.mLatSouth = southLatitude;
+ this.mLonWest = westLongitude;
+ }
+
+ /**
+ * Calculates the centerpoint of this LatLngBounds by simple interpolation and returns
+ * it as a point. This is a non-geodesic calculation which is not the geographic center.
+ *
+ * @return LatLng center of this LatLngBounds
+ */
+ public LatLng getCenter() {
+ return new LatLng((this.mLatNorth + this.mLatSouth) / 2,
+ (this.mLonEast + this.mLonWest) / 2);
+ }
+
+ public double getLatNorth() {
+ return this.mLatNorth;
+ }
+
+ public double getLatSouth() {
+ return this.mLatSouth;
+ }
+
+ public double getLonEast() {
+ return this.mLonEast;
+ }
+
+ public double getLonWest() {
+ return this.mLonWest;
+ }
+
+ /**
+ * Get the area spanned by this LatLngBounds
+ *
+ * @return LatLngSpan area
+ */
+ public LatLngSpan getSpan() {
+ return new LatLngSpan(getLatitudeSpan(), getLongitudeSpan());
+ }
+
+ /**
+ * Get the absolute distance, in degrees, between the north and
+ * south boundaries of this LatLngBounds
+ *
+ * @return Span distance
+ */
+ public double getLatitudeSpan() {
+ return Math.abs(this.mLatNorth - this.mLatSouth);
+ }
+
+ /**
+ * Get the absolute distance, in degrees, between the west and
+ * east boundaries of this LatLngBounds
+ *
+ * @return Span distance
+ */
+ public double getLongitudeSpan() {
+ return Math.abs(this.mLonEast - this.mLonWest);
+ }
+
+
+ /**
+ * Validate if LatLngBounds is empty, determined if absolute distance is
+ *
+ * @return boolean indicating if span is empty
+ */
+ public boolean isEmptySpan() {
+ return getLongitudeSpan() == 0.0 || getLatitudeSpan() == 0.0;
+ }
+
+ @Override
+ public String toString() {
+ return "N:" + this.mLatNorth + "; E:" + this.mLonEast + "; S:" + this.mLatSouth + "; W:" + this.mLonWest;
+ }
+
+ /**
+ * Constructs a LatLngBounds that contains all of a list of LatLng
+ * objects. Empty lists will yield invalid LatLngBounds.
+ *
+ * @param latLngs List of LatLng objects
+ * @return LatLngBounds
+ */
+ static LatLngBounds fromLatLngs(final List<? extends ILatLng> latLngs) {
+ double minLat = 90;
+ double minLon = 180;
+ double maxLat = -90;
+ double maxLon = -180;
+
+ for (final ILatLng gp : latLngs) {
+ final double latitude = gp.getLatitude();
+ final double longitude = gp.getLongitude();
+
+ minLat = Math.min(minLat, latitude);
+ minLon = Math.min(minLon, longitude);
+ maxLat = Math.max(maxLat, latitude);
+ maxLon = Math.max(maxLon, longitude);
}
- /**
- * Calculates the centerpoint of this LatLngBounds by simple interpolation and returns
- * it as a point. This is a non-geodesic calculation which is not the geographic center.
- *
- * @return LatLng center of this LatLngBounds
- */
- public LatLng getCenter() {
- return new LatLng((this.mLatNorth + this.mLatSouth) / 2,
- (this.mLonEast + this.mLonWest) / 2);
+ return new LatLngBounds(maxLat, maxLon, minLat, minLon);
+ }
+
+ public LatLng[] toLatLngs() {
+ return new LatLng[] {new LatLng(mLatNorth, mLonEast), new LatLng(mLatSouth, mLonWest)};
+ }
+
+ /**
+ * Determines whether this LatLngBounds matches another one via LatLng.
+ *
+ * @param o another object
+ * @return a boolean indicating whether the LatLngBounds are equal
+ */
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
}
-
- public double getLatNorth() {
- return this.mLatNorth;
- }
-
- public double getLatSouth() {
- return this.mLatSouth;
- }
-
- public double getLonEast() {
- return this.mLonEast;
- }
-
- public double getLonWest() {
- return this.mLonWest;
- }
-
- /**
- * Get the area spanned by this LatLngBounds
- *
- * @return LatLngSpan area
- */
- public LatLngSpan getSpan() {
- return new LatLngSpan(getLatitudeSpan(), getLongitudeSpan());
- }
-
- /**
- * Get the absolute distance, in degrees, between the north and
- * south boundaries of this LatLngBounds
- *
- * @return Span distance
- */
- public double getLatitudeSpan() {
- return Math.abs(this.mLatNorth - this.mLatSouth);
- }
-
- /**
- * Get the absolute distance, in degrees, between the west and
- * east boundaries of this LatLngBounds
- *
- * @return Span distance
- */
- public double getLongitudeSpan() {
- return Math.abs(this.mLonEast - this.mLonWest);
- }
-
-
- /**
- * Validate if LatLngBounds is empty, determined if absolute distance is
- *
- * @return boolean indicating if span is empty
- */
- public boolean isEmptySpan() {
- return getLongitudeSpan() == 0.0 || getLatitudeSpan() == 0.0;
- }
-
- @Override
- public String toString() {
- return "N:" + this.mLatNorth + "; E:" + this.mLonEast + "; S:" + this.mLatSouth + "; W:" + this.mLonWest;
+ if (o instanceof LatLngBounds) {
+ LatLngBounds other = (LatLngBounds) o;
+ return mLatNorth == other.getLatNorth()
+ && mLatSouth == other.getLatSouth()
+ && mLonEast == other.getLonEast()
+ && mLonWest == other.getLonWest();
}
-
- /**
- * Constructs a LatLngBounds that contains all of a list of LatLng
- * objects. Empty lists will yield invalid LatLngBounds.
- *
- * @param latLngs List of LatLng objects
- * @return LatLngBounds
- */
- static LatLngBounds fromLatLngs(final List<? extends ILatLng> latLngs) {
- double minLat = 90,
- minLon = 180,
- maxLat = -90,
- maxLon = -180;
-
- for (final ILatLng gp : latLngs) {
- final double latitude = gp.getLatitude();
- final double longitude = gp.getLongitude();
-
- minLat = Math.min(minLat, latitude);
- minLon = Math.min(minLon, longitude);
- maxLat = Math.max(maxLat, latitude);
- maxLon = Math.max(maxLon, longitude);
- }
-
- return new LatLngBounds(maxLat, maxLon, minLat, minLon);
- }
-
- public LatLng[] toLatLngs() {
- return new LatLng[]{new LatLng(mLatNorth, mLonEast), new LatLng(mLatSouth, mLonWest)};
- }
-
- /**
- * Determines whether this LatLngBounds matches another one via LatLng.
- *
- * @param o another object
- * @return a boolean indicating whether the LatLngBounds are equal
- */
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o instanceof LatLngBounds) {
- LatLngBounds other = (LatLngBounds) o;
- return mLatNorth == other.getLatNorth()
- && mLatSouth == other.getLatSouth()
- && mLonEast == other.getLonEast()
- && mLonWest == other.getLonWest();
- }
- return false;
- }
-
- /**
- * Determines whether this LatLngBounds contains a point and the point
- * does not touch its boundary.
- *
- * @param latLng the point which may be contained
- * @return true, if the point is contained within the box.
- */
- public boolean contains(final ILatLng latLng) {
- final double latitude = latLng.getLatitude();
- final double longitude = latLng.getLongitude();
- return ((latitude < this.mLatNorth)
- && (latitude > this.mLatSouth))
- && ((longitude < this.mLonEast)
- && (longitude > this.mLonWest));
- }
-
- /**
- * Returns a new LatLngBounds that stretches to contain both this and another LatLngBounds.
- *
- * @param bounds LatLngBounds to add
- * @return LatLngBounds
- */
- public LatLngBounds union(LatLngBounds bounds) {
- return union(bounds.getLatNorth(), bounds.getLonEast(), bounds.getLatSouth(), bounds.getLonWest());
+ return false;
+ }
+
+ /**
+ * Determines whether this LatLngBounds contains a point and the point
+ * does not touch its boundary.
+ *
+ * @param latLng the point which may be contained
+ * @return true, if the point is contained within the box.
+ */
+ public boolean contains(final ILatLng latLng) {
+ final double latitude = latLng.getLatitude();
+ final double longitude = latLng.getLongitude();
+ return ((latitude < this.mLatNorth)
+ && (latitude > this.mLatSouth))
+ && ((longitude < this.mLonEast)
+ && (longitude > this.mLonWest));
+ }
+
+ /**
+ * Returns a new LatLngBounds that stretches to contain both this and another LatLngBounds.
+ *
+ * @param bounds LatLngBounds to add
+ * @return LatLngBounds
+ */
+ public LatLngBounds union(LatLngBounds bounds) {
+ return union(bounds.getLatNorth(), bounds.getLonEast(), bounds.getLatSouth(), bounds.getLonWest());
+ }
+
+ /**
+ * Returns a new LatLngBounds that stretches to include another LatLngBounds,
+ * given by corner points.
+ *
+ * @param lonNorth Northern Longitude
+ * @param latEast Eastern Latitude
+ * @param lonSouth Southern Longitude
+ * @param latWest Western Longitude
+ * @return BoundingBox
+ */
+ public LatLngBounds union(final double lonNorth, final double latEast, final double lonSouth, final double latWest) {
+ return new LatLngBounds((this.mLatNorth < lonNorth) ? lonNorth : this.mLatNorth,
+ (this.mLonEast < latEast) ? latEast : this.mLonEast,
+ (this.mLatSouth > lonSouth) ? lonSouth : this.mLatSouth,
+ (this.mLonWest > latWest) ? latWest : this.mLonWest);
+ }
+
+ /**
+ * Returns a new LatLngBounds that is the intersection of this with another box
+ *
+ * @param box LatLngBounds to intersect with
+ * @return LatLngBounds
+ */
+ public LatLngBounds intersect(LatLngBounds box) {
+ double minLatWest = Math.max(getLonWest(), box.getLonWest());
+ double maxLatEast = Math.min(getLonEast(), box.getLonEast());
+ if (maxLatEast > minLatWest) {
+ double minLonSouth = Math.max(getLatSouth(), box.getLatSouth());
+ double maxLonNorth = Math.min(getLatNorth(), box.getLatNorth());
+ if (maxLonNorth > minLonSouth) {
+ return new LatLngBounds(maxLonNorth, maxLatEast, minLonSouth, minLatWest);
+ }
}
-
- /**
- * Returns a new LatLngBounds that stretches to include another LatLngBounds,
- * given by corner points.
- *
- * @param lonNorth Northern Longitude
- * @param latEast Eastern Latitude
- * @param lonSouth Southern Longitude
- * @param latWest Western Longitude
- * @return BoundingBox
- */
- public LatLngBounds union(final double lonNorth, final double latEast, final double lonSouth, final double latWest) {
- return new LatLngBounds((this.mLatNorth < lonNorth) ? lonNorth : this.mLatNorth,
- (this.mLonEast < latEast) ? latEast : this.mLonEast,
- (this.mLatSouth > lonSouth) ? lonSouth : this.mLatSouth,
- (this.mLonWest > latWest) ? latWest : this.mLonWest);
- }
-
- /**
- * Returns a new LatLngBounds that is the intersection of this with another box
- *
- * @param box LatLngBounds to intersect with
- * @return LatLngBounds
- */
- public LatLngBounds intersect(LatLngBounds box) {
- double minLatWest = Math.max(getLonWest(), box.getLonWest());
- double maxLatEast = Math.min(getLonEast(), box.getLonEast());
- if (maxLatEast > minLatWest) {
- double minLonSouth = Math.max(getLatSouth(), box.getLatSouth());
- double maxLonNorth = Math.min(getLatNorth(), box.getLatNorth());
- if (maxLonNorth > minLonSouth) {
- return new LatLngBounds(maxLonNorth, maxLatEast, minLonSouth, minLatWest);
- }
- }
- return null;
- }
-
- /**
- * Returns a new LatLngBounds that is the intersection of this with another LatLngBounds
- *
- * @param northLatitude Northern Longitude
- * @param eastLongitude Eastern Latitude
- * @param southLatitude Southern Longitude
- * @param westLongitude Western Latitude
- * @return LatLngBounds
- */
- public LatLngBounds intersect(double northLatitude, double eastLongitude, double southLatitude, double westLongitude) {
- return intersect(new LatLngBounds(northLatitude, eastLongitude, southLatitude, westLongitude));
- }
-
- public static final Parcelable.Creator<LatLngBounds> CREATOR =
- new Parcelable.Creator<LatLngBounds>() {
- @Override
- public LatLngBounds createFromParcel(final Parcel in) {
- return readFromParcel(in);
- }
-
- @Override
- public LatLngBounds[] newArray(final int size) {
- return new LatLngBounds[size];
- }
- };
-
- @Override
- public int hashCode() {
- return (int) ((mLatNorth + 90)
- + ((mLatSouth + 90) * 1000)
- + ((mLonEast + 180) * 1000000)
- + ((mLonEast + 180) * 1000000000));
- }
-
- @Override
- public int describeContents() {
- return 0;
+ return null;
+ }
+
+ /**
+ * Returns a new LatLngBounds that is the intersection of this with another LatLngBounds
+ *
+ * @param northLatitude Northern Longitude
+ * @param eastLongitude Eastern Latitude
+ * @param southLatitude Southern Longitude
+ * @param westLongitude Western Latitude
+ * @return LatLngBounds
+ */
+ public LatLngBounds intersect(double northLatitude, double eastLongitude, double southLatitude,
+ double westLongitude) {
+ return intersect(new LatLngBounds(northLatitude, eastLongitude, southLatitude, westLongitude));
+ }
+
+ public static final Parcelable.Creator<LatLngBounds> CREATOR =
+ new Parcelable.Creator<LatLngBounds>() {
+ @Override
+ public LatLngBounds createFromParcel(final Parcel in) {
+ return readFromParcel(in);
+ }
+
+ @Override
+ public LatLngBounds[] newArray(final int size) {
+ return new LatLngBounds[size];
+ }
+ };
+
+ @Override
+ public int hashCode() {
+ return (int) ((mLatNorth + 90)
+ + ((mLatSouth + 90) * 1000)
+ + ((mLonEast + 180) * 1000000)
+ + ((mLonEast + 180) * 1000000000));
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(final Parcel out, final int arg1) {
+ out.writeDouble(this.mLatNorth);
+ out.writeDouble(this.mLonEast);
+ out.writeDouble(this.mLatSouth);
+ out.writeDouble(this.mLonWest);
+ }
+
+ private static LatLngBounds readFromParcel(final Parcel in) {
+ final double lonNorth = in.readDouble();
+ final double latEast = in.readDouble();
+ final double lonSouth = in.readDouble();
+ final double latWest = in.readDouble();
+ return new LatLngBounds(lonNorth, latEast, lonSouth, latWest);
+ }
+
+ /**
+ * Builder for composing LatLngBounds objects.
+ */
+ public static final class Builder {
+
+ private List<LatLng> mLatLngList;
+
+ public Builder() {
+ mLatLngList = new ArrayList<>();
}
- @Override
- public void writeToParcel(final Parcel out, final int arg1) {
- out.writeDouble(this.mLatNorth);
- out.writeDouble(this.mLonEast);
- out.writeDouble(this.mLatSouth);
- out.writeDouble(this.mLonWest);
+ public LatLngBounds build() {
+ if (mLatLngList.size() < 2) {
+ throw new InvalidLatLngBoundsException(mLatLngList.size());
+ }
+ return LatLngBounds.fromLatLngs(mLatLngList);
}
- private static LatLngBounds readFromParcel(final Parcel in) {
- final double lonNorth = in.readDouble();
- final double latEast = in.readDouble();
- final double lonSouth = in.readDouble();
- final double latWest = in.readDouble();
- return new LatLngBounds(lonNorth, latEast, lonSouth, latWest);
+ public Builder includes(List<LatLng> latLngs) {
+ for (LatLng point : latLngs) {
+ mLatLngList.add(point);
+ }
+ return this;
}
- /**
- * Builder for composing LatLngBounds objects.
- */
- public static final class Builder {
-
- private List<LatLng> mLatLngList;
-
- public Builder() {
- mLatLngList = new ArrayList<>();
- }
-
- public LatLngBounds build() {
- if (mLatLngList.size() < 2) {
- throw new InvalidLatLngBoundsException(mLatLngList.size());
- }
- return LatLngBounds.fromLatLngs(mLatLngList);
- }
-
- public Builder includes(List<LatLng> latLngs){
- for (LatLng point : latLngs) {
- mLatLngList.add(point);
- }
- return this;
- }
-
- public Builder include(@NonNull LatLng latLng) {
- mLatLngList.add(latLng);
- return this;
- }
+ public Builder include(@NonNull LatLng latLng) {
+ mLatLngList.add(latLng);
+ return this;
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java
index 81e52666f6..dd7fef4d23 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java
@@ -9,93 +9,95 @@ import android.support.annotation.NonNull;
*/
public class LatLngSpan implements Parcelable {
- private double mLatitudeSpan;
- private double mLongitudeSpan;
+ private double mLatitudeSpan;
+ private double mLongitudeSpan;
- private LatLngSpan(@NonNull Parcel in) {
- mLatitudeSpan = in.readDouble();
- mLongitudeSpan = in.readDouble();
- }
+ private LatLngSpan(@NonNull Parcel in) {
+ mLatitudeSpan = in.readDouble();
+ mLongitudeSpan = in.readDouble();
+ }
- /**
- * Creates a LatLgnSpan.
- *
- * @param latitudeSpan The span used for latitude.
- * @param longitudeSpan The span used for longitude.
- */
- public LatLngSpan(double latitudeSpan, double longitudeSpan) {
- mLatitudeSpan = latitudeSpan;
- mLongitudeSpan = longitudeSpan;
- }
+ /**
+ * Creates a LatLgnSpan.
+ *
+ * @param latitudeSpan The span used for latitude.
+ * @param longitudeSpan The span used for longitude.
+ */
+ public LatLngSpan(double latitudeSpan, double longitudeSpan) {
+ mLatitudeSpan = latitudeSpan;
+ mLongitudeSpan = longitudeSpan;
+ }
- /**
- * Returns the latitude span.
- *
- * @return The latitude span.
- */
- public double getLatitudeSpan() {
- return mLatitudeSpan;
- }
+ /**
+ * Returns the latitude span.
+ *
+ * @return The latitude span.
+ */
+ public double getLatitudeSpan() {
+ return mLatitudeSpan;
+ }
- /**
- * Sets the latitude span.
- *
- * @param latitudeSpan The latitude span to set.
- */
- public void setLatitudeSpan(double latitudeSpan) {
- mLatitudeSpan = latitudeSpan;
- }
+ /**
+ * Sets the latitude span.
+ *
+ * @param latitudeSpan The latitude span to set.
+ */
+ public void setLatitudeSpan(double latitudeSpan) {
+ mLatitudeSpan = latitudeSpan;
+ }
- /**
- * Returns to longitude span.
- *
- * @return The longitude span.
- */
- public double getLongitudeSpan() {
- return mLongitudeSpan;
- }
+ /**
+ * Returns to longitude span.
+ *
+ * @return The longitude span.
+ */
+ public double getLongitudeSpan() {
+ return mLongitudeSpan;
+ }
- /**
- * Sets the longitude span.
- *
- * @param longitudeSpan The longitude span to set.
- */
- public void setLongitudeSpan(double longitudeSpan) {
- mLongitudeSpan = longitudeSpan;
- }
+ /**
+ * Sets the longitude span.
+ *
+ * @param longitudeSpan The longitude span to set.
+ */
+ public void setLongitudeSpan(double longitudeSpan) {
+ mLongitudeSpan = longitudeSpan;
+ }
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o instanceof LatLngSpan) {
- LatLngSpan other = (LatLngSpan) o;
- return mLongitudeSpan == other.getLongitudeSpan()
- && mLatitudeSpan == other.getLatitudeSpan();
- }
- return false;
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o instanceof LatLngSpan) {
+ LatLngSpan other = (LatLngSpan) o;
+ return mLongitudeSpan == other.getLongitudeSpan()
+ && mLatitudeSpan == other.getLatitudeSpan();
}
+ return false;
+ }
- public static final Parcelable.Creator<LatLngSpan> CREATOR =
- new Parcelable.Creator<LatLngSpan>() {
- @Override
- public LatLngSpan createFromParcel(Parcel in) {
- return new LatLngSpan(in);
- }
+ public static final Parcelable.Creator<LatLngSpan> CREATOR =
+ new Parcelable.Creator<LatLngSpan>() {
+ @Override
+ public LatLngSpan createFromParcel(Parcel in) {
+ return new LatLngSpan(in);
+ }
- @Override
- public LatLngSpan[] newArray(int size) {
- return new LatLngSpan[size];
- }
- };
+ @Override
+ public LatLngSpan[] newArray(int size) {
+ return new LatLngSpan[size];
+ }
+ };
- @Override
- public int describeContents() {
- return 0;
- }
+ @Override
+ public int describeContents() {
+ return 0;
+ }
- @Override
- public void writeToParcel(Parcel out, int arg1) {
- out.writeDouble(mLatitudeSpan);
- out.writeDouble(mLongitudeSpan);
- }
+ @Override
+ public void writeToParcel(Parcel out, int arg1) {
+ out.writeDouble(mLatitudeSpan);
+ out.writeDouble(mLongitudeSpan);
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java
index 1f1417b4b6..761d8f2a8b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java
@@ -13,104 +13,105 @@ import android.os.Parcelable;
*/
public class ProjectedMeters implements IProjectedMeters, Parcelable {
- public static final Creator<ProjectedMeters> CREATOR = new Creator<ProjectedMeters>() {
- public ProjectedMeters createFromParcel(Parcel in) {
- return new ProjectedMeters(in);
- }
-
- public ProjectedMeters[] newArray(int size) {
- return new ProjectedMeters[size];
- }
- };
-
- private double northing;
- private double easting;
-
- /**
- * Creates a ProjectedMeters based on projected meters in north and east direction.
- *
- * @param northing the northing in meters
- * @param easting the easting in meters
- */
- public ProjectedMeters(double northing, double easting) {
- this.northing = northing;
- this.easting = easting;
+ public static final Creator<ProjectedMeters> CREATOR = new Creator<ProjectedMeters>() {
+ public ProjectedMeters createFromParcel(Parcel in) {
+ return new ProjectedMeters(in);
}
- /**
- * Creates a ProjecteMeters based on another set of projected meters.
- *
- * @param projectedMeters The projected meters to be based on.
- */
- public ProjectedMeters(ProjectedMeters projectedMeters) {
- this.northing = projectedMeters.northing;
- this.easting = projectedMeters.easting;
+ public ProjectedMeters[] newArray(int size) {
+ return new ProjectedMeters[size];
}
-
- private ProjectedMeters(Parcel in) {
- northing = in.readDouble();
- easting = in.readDouble();
- }
-
- /**
- * Get projected meters in north direction.
- *
- * @return Projected meters in north.
- */
- @Override
- public double getNorthing() {
- return northing;
- }
-
- /**
- * Get projected meters in east direction.
- *
- * @return Projected meters in east.
- */
- @Override
- public double getEasting() {
- return easting;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- ProjectedMeters projectedMeters = (ProjectedMeters) o;
-
- return Double.compare(projectedMeters.easting, easting) == 0 && Double.compare(projectedMeters.northing, northing) == 0;
-
- }
-
- @Override
- public int hashCode() {
- int result;
- long temp;
- temp = Double.doubleToLongBits(easting);
- result = (int) (temp ^ (temp >>> 32));
- temp = Double.doubleToLongBits(northing);
- result = 31 * result + (int) (temp ^ (temp >>> 32));
- return result;
+ };
+
+ private double northing;
+ private double easting;
+
+ /**
+ * Creates a ProjectedMeters based on projected meters in north and east direction.
+ *
+ * @param northing the northing in meters
+ * @param easting the easting in meters
+ */
+ public ProjectedMeters(double northing, double easting) {
+ this.northing = northing;
+ this.easting = easting;
+ }
+
+ /**
+ * Creates a ProjecteMeters based on another set of projected meters.
+ *
+ * @param projectedMeters The projected meters to be based on.
+ */
+ public ProjectedMeters(ProjectedMeters projectedMeters) {
+ this.northing = projectedMeters.northing;
+ this.easting = projectedMeters.easting;
+ }
+
+ private ProjectedMeters(Parcel in) {
+ northing = in.readDouble();
+ easting = in.readDouble();
+ }
+
+ /**
+ * Get projected meters in north direction.
+ *
+ * @return Projected meters in north.
+ */
+ @Override
+ public double getNorthing() {
+ return northing;
+ }
+
+ /**
+ * Get projected meters in east direction.
+ *
+ * @return Projected meters in east.
+ */
+ @Override
+ public double getEasting() {
+ return easting;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
}
-
- @Override
- public String toString() {
- return "ProjectedMeters [northing=" + northing + ", easting=" + easting + "]";
- }
-
- @Override
- public int describeContents() {
- return 0;
+ if (o == null || getClass() != o.getClass()) {
+ return false;
}
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeDouble(northing);
- out.writeDouble(easting);
- }
+ ProjectedMeters projectedMeters = (ProjectedMeters) o;
+
+ return Double.compare(projectedMeters.easting, easting) == 0
+ && Double.compare(projectedMeters.northing, northing) == 0;
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result;
+ long temp;
+ temp = Double.doubleToLongBits(easting);
+ result = (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(northing);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "ProjectedMeters [northing=" + northing + ", easting=" + easting + "]";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeDouble(northing);
+ out.writeDouble(easting);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java
index de562c3632..45300f248c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java
@@ -12,118 +12,119 @@ import android.os.Parcelable;
*/
public class VisibleRegion implements Parcelable {
- /**
- * LatLng object that defines the far left corner of the camera.
- */
- public final LatLng farLeft;
-
- /**
- * LatLng object that defines the far right corner of the camera.
- */
- public final LatLng farRight;
-
- /**
- * LatLng object that defines the bottom left corner of the camera.
- */
- public final LatLng nearLeft;
-
- /**
- * LatLng object that defines the bottom right corner of the camera.
- */
- public final LatLng nearRight;
-
- /**
- * The smallest bounding box that includes the visible region defined in this class.
- */
- public final LatLngBounds latLngBounds;
-
- private VisibleRegion(Parcel in) {
- this.farLeft = in.readParcelable(LatLng.class.getClassLoader());
- this.farRight = in.readParcelable(LatLng.class.getClassLoader());
- this.nearLeft = in.readParcelable(LatLng.class.getClassLoader());
- this.nearRight = in.readParcelable(LatLng.class.getClassLoader());
- this.latLngBounds = in.readParcelable(LatLngBounds.class.getClassLoader());
+ /**
+ * LatLng object that defines the far left corner of the camera.
+ */
+ public final LatLng farLeft;
+
+ /**
+ * LatLng object that defines the far right corner of the camera.
+ */
+ public final LatLng farRight;
+
+ /**
+ * LatLng object that defines the bottom left corner of the camera.
+ */
+ public final LatLng nearLeft;
+
+ /**
+ * LatLng object that defines the bottom right corner of the camera.
+ */
+ public final LatLng nearRight;
+
+ /**
+ * The smallest bounding box that includes the visible region defined in this class.
+ */
+ public final LatLngBounds latLngBounds;
+
+ private VisibleRegion(Parcel in) {
+ this.farLeft = in.readParcelable(LatLng.class.getClassLoader());
+ this.farRight = in.readParcelable(LatLng.class.getClassLoader());
+ this.nearLeft = in.readParcelable(LatLng.class.getClassLoader());
+ this.nearRight = in.readParcelable(LatLng.class.getClassLoader());
+ this.latLngBounds = in.readParcelable(LatLngBounds.class.getClassLoader());
+ }
+
+ /**
+ * Creates a new VisibleRegion given the four corners of the camera.
+ *
+ * @param farLeft A LatLng object containing the latitude and longitude of the near left corner of the region.
+ * @param farRight A LatLng object containing the latitude and longitude of the near left corner of the region.
+ * @param nearLeft A LatLng object containing the latitude and longitude of the near left corner of the region.
+ * @param nearRight A LatLng object containing the latitude and longitude of the near left corner of the region.
+ * @param latLngBounds The smallest bounding box that includes the visible region defined in this class.
+ */
+ public VisibleRegion(LatLng farLeft, LatLng farRight, LatLng nearLeft, LatLng nearRight, LatLngBounds latLngBounds) {
+ this.farLeft = farLeft;
+ this.farRight = farRight;
+ this.nearLeft = nearLeft;
+ this.nearRight = nearRight;
+ this.latLngBounds = latLngBounds;
+ }
+
+ /**
+ * Compares this VisibleRegion to another object.
+ * If the other object is actually a pointer to this object,
+ * or if all four corners and the bounds of the two objects are the same,
+ * this method returns true. Otherwise, this method returns false.
+ *
+ * @param o The Object to compare with.
+ * @return true if both objects are the same object.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof VisibleRegion)) {
+ return false;
}
-
- /**
- * Creates a new VisibleRegion given the four corners of the camera.
- *
- * @param farLeft A LatLng object containing the latitude and longitude of the near left corner of the region.
- * @param farRight A LatLng object containing the latitude and longitude of the near left corner of the region.
- * @param nearLeft A LatLng object containing the latitude and longitude of the near left corner of the region.
- * @param nearRight A LatLng object containing the latitude and longitude of the near left corner of the region.
- * @param latLngBounds The smallest bounding box that includes the visible region defined in this class.
- */
- public VisibleRegion(LatLng farLeft, LatLng farRight, LatLng nearLeft, LatLng nearRight, LatLngBounds latLngBounds) {
- this.farLeft = farLeft;
- this.farRight = farRight;
- this.nearLeft = nearLeft;
- this.nearRight = nearRight;
- this.latLngBounds = latLngBounds;
- }
-
- /**
- * Compares this VisibleRegion to another object.
- * If the other object is actually a pointer to this object,
- * or if all four corners and the bounds of the two objects are the same,
- * this method returns true. Otherwise, this method returns false.
- *
- * @param o The Object to compare with.
- * @return true if both objects are the same object.
- */
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof VisibleRegion)) {
- return false;
- }
- if (o == this) {
- return true;
- }
-
- VisibleRegion visibleRegion = (VisibleRegion) o;
- return farLeft.equals(visibleRegion.farLeft)
- && farRight.equals(visibleRegion.farRight)
- && nearLeft.equals(visibleRegion.nearLeft)
- && nearRight.equals(visibleRegion.nearRight)
- && latLngBounds.equals(visibleRegion.latLngBounds);
- }
-
- @Override
- public String toString() {
- return "[farLeft [" + farLeft + "], farRight [" + farRight + "], nearLeft [" + nearLeft + "], nearRight [" + nearRight + "], latLngBounds [" + latLngBounds + "]]";
- }
-
- @Override
- public int hashCode() {
- return ((farLeft.hashCode() + 90)
- + ((farRight.hashCode() + 90) * 1000)
- + ((nearLeft.hashCode() + 180) * 1000000)
- + ((nearRight.hashCode() + 180) * 1000000000));
- }
-
- @Override
- public int describeContents() {
- return 0;
+ if (o == this) {
+ return true;
}
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(farLeft, flags);
- out.writeParcelable(farRight, flags);
- out.writeParcelable(nearLeft, flags);
- out.writeParcelable(nearRight, flags);
- out.writeParcelable(latLngBounds, flags);
- }
-
- public static final Parcelable.Creator<VisibleRegion> CREATOR
- = new Parcelable.Creator<VisibleRegion>() {
- public VisibleRegion createFromParcel(Parcel in) {
- return new VisibleRegion(in);
- }
-
- public VisibleRegion[] newArray(int size) {
- return new VisibleRegion[size];
- }
+ VisibleRegion visibleRegion = (VisibleRegion) o;
+ return farLeft.equals(visibleRegion.farLeft)
+ && farRight.equals(visibleRegion.farRight)
+ && nearLeft.equals(visibleRegion.nearLeft)
+ && nearRight.equals(visibleRegion.nearRight)
+ && latLngBounds.equals(visibleRegion.latLngBounds);
+ }
+
+ @Override
+ public String toString() {
+ return "[farLeft [" + farLeft + "], farRight [" + farRight + "], nearLeft [" + nearLeft + "], nearRight ["
+ + nearRight + "], latLngBounds [" + latLngBounds + "]]";
+ }
+
+ @Override
+ public int hashCode() {
+ return ((farLeft.hashCode() + 90)
+ + ((farRight.hashCode() + 90) * 1000)
+ + ((nearLeft.hashCode() + 180) * 1000000)
+ + ((nearRight.hashCode() + 180) * 1000000000));
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(farLeft, flags);
+ out.writeParcelable(farRight, flags);
+ out.writeParcelable(nearLeft, flags);
+ out.writeParcelable(nearRight, flags);
+ out.writeParcelable(latLngBounds, flags);
+ }
+
+ public static final Parcelable.Creator<VisibleRegion> CREATOR =
+ new Parcelable.Creator<VisibleRegion>() {
+ public VisibleRegion createFromParcel(Parcel in) {
+ return new VisibleRegion(in);
+ }
+
+ public VisibleRegion[] newArray(int size) {
+ return new VisibleRegion[size];
+ }
};
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java
index 430b37adb8..2c6251638a 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java
@@ -5,10 +5,9 @@ import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.Build;
import android.text.TextUtils;
-import android.util.Log;
import com.mapbox.mapboxsdk.BuildConfig;
-import com.mapbox.mapboxsdk.MapboxAccountManager;
+import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import java.io.IOException;
@@ -28,176 +27,179 @@ import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.internal.Util;
+import timber.log.Timber;
class HTTPRequest implements Callback {
- private static OkHttpClient mClient = new OkHttpClient();
- private static final String LOG_TAG = HTTPRequest.class.getName();
- private String USER_AGENT_STRING = null;
-
- private static final int CONNECTION_ERROR = 0;
- private static final int TEMPORARY_ERROR = 1;
- private static final int PERMANENT_ERROR = 2;
-
- // Reentrancy is not needed, but "Lock" is an
- // abstract class.
- private ReentrantLock mLock = new ReentrantLock();
-
- private long mNativePtr = 0;
-
- private Call mCall;
- private Request mRequest;
-
- private native void nativeOnFailure(int type, String message);
-
- private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires, String retryAfter, String xRateLimitReset, byte[] body);
-
- private HTTPRequest(long nativePtr, String resourceUrl, String etag, String modified) {
- mNativePtr = nativePtr;
-
- try {
- // Don't try a request if we aren't connected
- if (!MapboxAccountManager.getInstance().isConnected()) {
- throw new NoRouteToHostException("No Internet connection available.");
- }
-
- HttpUrl httpUrl = HttpUrl.parse(resourceUrl);
- final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE);
- if (host.equals("mapbox.com") || host.endsWith(".mapbox.com") || host.equals("mapbox.cn") || host.endsWith(".mapbox.cn")) {
- if (httpUrl.querySize() == 0) {
- resourceUrl = resourceUrl + "?";
- } else {
- resourceUrl = resourceUrl + "&";
- }
- resourceUrl = resourceUrl + "events=true";
- }
-
- Request.Builder builder = new Request.Builder()
- .url(resourceUrl)
- .tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE))
- .addHeader("User-Agent", getUserAgent());
- if (etag.length() > 0) {
- builder = builder.addHeader("If-None-Match", etag);
- } else if (modified.length() > 0) {
- builder = builder.addHeader("If-Modified-Since", modified);
- }
- mRequest = builder.build();
- mCall = mClient.newCall(mRequest);
- mCall.enqueue(this);
- } catch (Exception e) {
- onFailure(e);
- }
- }
+ private static OkHttpClient mClient = new OkHttpClient();
+ private String USER_AGENT_STRING = null;
- public void cancel() {
- // mCall can be null if the constructor gets aborted (e.g, under a NoRouteToHostException).
- if (mCall != null) {
- mCall.cancel();
- }
+ private static final int CONNECTION_ERROR = 0;
+ private static final int TEMPORARY_ERROR = 1;
+ private static final int PERMANENT_ERROR = 2;
- // TODO: We need a lock here because we can try
- // to cancel at the same time the request is getting
- // answered on the OkHTTP thread. We could get rid of
- // this lock by using Runnable when we move Android
- // implementation of mbgl::RunLoop to Looper.
- mLock.lock();
- mNativePtr = 0;
- mLock.unlock();
- }
+ // Reentrancy is not needed, but "Lock" is an
+ // abstract class.
+ private ReentrantLock mLock = new ReentrantLock();
- @Override
- public void onResponse(Call call, Response response) throws IOException {
- if (response.isSuccessful()) {
- Log.v(LOG_TAG, String.format("[HTTP] Request was successful (code = %d).", response.code()));
- } else {
- // We don't want to call this unsuccessful because a 304 isn't really an error
- String message = !TextUtils.isEmpty(response.message()) ? response.message() : "No additional information";
- Log.d(LOG_TAG, String.format(
- "[HTTP] Request with response code = %d: %s",
- response.code(), message));
- }
+ private long mNativePtr = 0;
- byte[] body;
- try {
- body = response.body().bytes();
- } catch (IOException e) {
- onFailure(e);
- //throw e;
- return;
- } finally {
- response.body().close();
- }
+ private Call mCall;
+ private Request mRequest;
- mLock.lock();
- if (mNativePtr != 0) {
- nativeOnResponse(response.code(),
- response.header("ETag"),
- response.header("Last-Modified"),
- response.header("Cache-Control"),
- response.header("Expires"),
- response.header("Retry-After"),
- response.header("x-rate-limit-reset"),
- body);
- }
- mLock.unlock();
- }
+ private native void nativeOnFailure(int type, String message);
- @Override
- public void onFailure(Call call, IOException e) {
- onFailure(e);
- }
+ private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires,
+ String retryAfter, String xRateLimitReset, byte[] body);
- private void onFailure(Exception e) {
- int type = PERMANENT_ERROR;
- if ((e instanceof NoRouteToHostException) || (e instanceof UnknownHostException) || (e instanceof SocketException) || (e instanceof ProtocolException) || (e instanceof SSLException)) {
- type = CONNECTION_ERROR;
- } else if ((e instanceof InterruptedIOException)) {
- type = TEMPORARY_ERROR;
- }
+ private HTTPRequest(long nativePtr, String resourceUrl, String etag, String modified) {
+ mNativePtr = nativePtr;
- String errorMessage = e.getMessage() != null ? e.getMessage() : "Error processing the request";
+ try {
+ // Don't try a request if we aren't connected
+ if (!Mapbox.isConnected()) {
+ throw new NoRouteToHostException("No Internet connection available.");
+ }
- if (type == TEMPORARY_ERROR) {
- Log.d(LOG_TAG, String.format(MapboxConstants.MAPBOX_LOCALE,
- "Request failed due to a temporary error: %s", errorMessage));
- } else if (type == CONNECTION_ERROR) {
- Log.i(LOG_TAG, String.format(MapboxConstants.MAPBOX_LOCALE,
- "Request failed due to a connection error: %s", errorMessage));
+ HttpUrl httpUrl = HttpUrl.parse(resourceUrl);
+ final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE);
+ if (host.equals("mapbox.com") || host.endsWith(".mapbox.com") || host.equals("mapbox.cn")
+ || host.endsWith(".mapbox.cn")) {
+ if (httpUrl.querySize() == 0) {
+ resourceUrl = resourceUrl + "?";
} else {
- // PERMANENT_ERROR
- Log.w(LOG_TAG, String.format(MapboxConstants.MAPBOX_LOCALE,
- "Request failed due to a permanent error: %s", errorMessage));
+ resourceUrl = resourceUrl + "&";
}
+ resourceUrl = resourceUrl + "events=true";
+ }
+
+ Request.Builder builder = new Request.Builder()
+ .url(resourceUrl)
+ .tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE))
+ .addHeader("User-Agent", getUserAgent());
+ if (etag.length() > 0) {
+ builder = builder.addHeader("If-None-Match", etag);
+ } else if (modified.length() > 0) {
+ builder = builder.addHeader("If-Modified-Since", modified);
+ }
+ mRequest = builder.build();
+ mCall = mClient.newCall(mRequest);
+ mCall.enqueue(this);
+ } catch (Exception exception) {
+ onFailure(exception);
+ }
+ }
- mLock.lock();
- if (mNativePtr != 0) {
- nativeOnFailure(type, errorMessage);
- }
- mLock.unlock();
+ public void cancel() {
+ // mCall can be null if the constructor gets aborted (e.g, under a NoRouteToHostException).
+ if (mCall != null) {
+ mCall.cancel();
}
- private String getUserAgent() {
- if (USER_AGENT_STRING == null) {
- return USER_AGENT_STRING = Util.toHumanReadableAscii(
- String.format("%s %s (%s) Android/%s (%s)",
- getApplicationIdentifier(),
- BuildConfig.MAPBOX_VERSION_STRING,
- BuildConfig.GIT_REVISION_SHORT,
- Build.VERSION.SDK_INT,
- Build.CPU_ABI)
- );
- } else {
- return USER_AGENT_STRING;
- }
+ // TODO: We need a lock here because we can try
+ // to cancel at the same time the request is getting
+ // answered on the OkHTTP thread. We could get rid of
+ // this lock by using Runnable when we move Android
+ // implementation of mbgl::RunLoop to Looper.
+ mLock.lock();
+ mNativePtr = 0;
+ mLock.unlock();
+ }
+
+ @Override
+ public void onResponse(Call call, Response response) throws IOException {
+ if (response.isSuccessful()) {
+ Timber.v(String.format("[HTTP] Request was successful (code = %d).", response.code()));
+ } else {
+ // We don't want to call this unsuccessful because a 304 isn't really an error
+ String message = !TextUtils.isEmpty(response.message()) ? response.message() : "No additional information";
+ Timber.d(String.format(
+ "[HTTP] Request with response code = %d: %s",
+ response.code(), message));
}
- private String getApplicationIdentifier() {
- try {
- Context context = MapboxAccountManager.getInstance().getApplicationContext();
- PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
- return String.format("%s/%s (%s)", context.getPackageName(), packageInfo.versionName, packageInfo.versionCode);
- } catch (Exception e) {
- return "";
- }
+ byte[] body;
+ try {
+ body = response.body().bytes();
+ } catch (IOException ioException) {
+ onFailure(ioException);
+ //throw ioException;
+ return;
+ } finally {
+ response.body().close();
+ }
+
+ mLock.lock();
+ if (mNativePtr != 0) {
+ nativeOnResponse(response.code(),
+ response.header("ETag"),
+ response.header("Last-Modified"),
+ response.header("Cache-Control"),
+ response.header("Expires"),
+ response.header("Retry-After"),
+ response.header("x-rate-limit-reset"),
+ body);
+ }
+ mLock.unlock();
+ }
+
+ @Override
+ public void onFailure(Call call, IOException e) {
+ onFailure(e);
+ }
+
+ private void onFailure(Exception e) {
+ int type = PERMANENT_ERROR;
+ if ((e instanceof NoRouteToHostException) || (e instanceof UnknownHostException) || (e instanceof SocketException)
+ || (e instanceof ProtocolException) || (e instanceof SSLException)) {
+ type = CONNECTION_ERROR;
+ } else if ((e instanceof InterruptedIOException)) {
+ type = TEMPORARY_ERROR;
+ }
+
+ String errorMessage = e.getMessage() != null ? e.getMessage() : "Error processing the request";
+
+ if (type == TEMPORARY_ERROR) {
+ Timber.d(String.format(MapboxConstants.MAPBOX_LOCALE,
+ "Request failed due to a temporary error: %s", errorMessage));
+ } else if (type == CONNECTION_ERROR) {
+ Timber.i(String.format(MapboxConstants.MAPBOX_LOCALE,
+ "Request failed due to a connection error: %s", errorMessage));
+ } else {
+ // PERMANENT_ERROR
+ Timber.w(String.format(MapboxConstants.MAPBOX_LOCALE,
+ "Request failed due to a permanent error: %s", errorMessage));
+ }
+
+ mLock.lock();
+ if (mNativePtr != 0) {
+ nativeOnFailure(type, errorMessage);
+ }
+ mLock.unlock();
+ }
+
+ private String getUserAgent() {
+ if (USER_AGENT_STRING == null) {
+ return USER_AGENT_STRING = Util.toHumanReadableAscii(
+ String.format("%s %s (%s) Android/%s (%s)",
+ getApplicationIdentifier(),
+ BuildConfig.MAPBOX_VERSION_STRING,
+ BuildConfig.GIT_REVISION_SHORT,
+ Build.VERSION.SDK_INT,
+ Build.CPU_ABI)
+ );
+ } else {
+ return USER_AGENT_STRING;
+ }
+ }
+
+ private String getApplicationIdentifier() {
+ try {
+ Context context = Mapbox.getApplicationContext();
+ PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
+ return String.format("%s/%s (%s)", context.getPackageName(), packageInfo.versionName, packageInfo.versionCode);
+ } catch (Exception exception) {
+ return "";
}
-}
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationListener.java
index eb8c4100dc..7d86d8b096 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationListener.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationListener.java
@@ -7,10 +7,11 @@ import android.location.Location;
*/
public interface LocationListener {
- /**
- * Callback method for receiving location updates from LocationServices.
- * @param location The new Location data
- */
- void onLocationChanged(Location location);
+ /**
+ * Callback method for receiving location updates from LocationServices.
+ *
+ * @param location The new Location data
+ */
+ void onLocationChanged(Location location);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java
index 4fade484b4..aaf08c8b55 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java
@@ -8,7 +8,9 @@ import android.location.Location;
import android.location.LocationManager;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
-import android.util.Log;
+import android.support.v4.content.LocalBroadcastManager;
+
+import timber.log.Timber;
import com.mapbox.mapboxsdk.telemetry.TelemetryLocationReceiver;
import com.mapzen.android.lost.api.LocationRequest;
@@ -16,174 +18,196 @@ import com.mapzen.android.lost.api.LostApiClient;
import java.util.concurrent.CopyOnWriteArrayList;
+import static com.mapzen.android.lost.api.LocationServices.FusedLocationApi;
+
/**
* Manages locational updates. Contains methods to register and unregister location listeners.
* <ul>
- * <li>You can register a {@link LocationListener} with {@link #addLocationListener(LocationListener)} to receive location updates.</li>
+ * <li>You can register a {@link LocationListener} with {@link #addLocationListener(LocationListener)} to receive
+ * location updates.</li>
* <li> You can unregister a {@link LocationListener} with {@link #removeLocationListener(LocationListener)}.</li>
* </ul>
* <p>
- * Note: If registering a listener in your Activity.onResume() implementation, you should unregister it in Activity.onPause().
- * (You won't receive location updates when paused, and this will cut down on unnecessary system overhead).
- * Do not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back in the history stack.
+ * Note: If registering a listener in your Activity.onStart() implementation, you should unregister it in
+ * Activity.onStop(). (You won't receive location updates when paused, and this will cut down on unnecessary system
+ * overhead). Do not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back
+ * in the history stack.
* </p>
*/
-public class LocationServices implements com.mapzen.android.lost.api.LocationListener {
-
- private static final String TAG = "LocationServices";
-
- private static LocationServices instance;
-
- private Context context;
- private LostApiClient locationClient;
- private Location lastLocation;
-
- private CopyOnWriteArrayList<LocationListener> locationListeners;
-
- private boolean isGPSEnabled;
-
- /**
- * Private constructor for singleton LocationServices
- */
- private LocationServices(Context context) {
- super();
- this.context = context;
- // Setup location services
- locationClient = new LostApiClient.Builder(context).build();
- locationListeners = new CopyOnWriteArrayList<>();
+public class LocationServices implements LostApiClient.ConnectionCallbacks,
+ com.mapzen.android.lost.api.LocationListener {
+
+ private static LocationServices instance;
+
+ private Context context;
+ private LostApiClient locationClient;
+ private Location lastLocation;
+
+ private CopyOnWriteArrayList<LocationListener> locationListeners;
+
+ private boolean isGpsEnabled;
+
+ /**
+ * Private constructor for singleton LocationServices
+ */
+ private LocationServices(Context context) {
+ super();
+ this.context = context;
+ // Setup location services
+ locationClient = new LostApiClient.Builder(context).addConnectionCallbacks(this).build();
+ locationListeners = new CopyOnWriteArrayList<>();
+ }
+
+ /**
+ * Primary (singleton) access method for LocationServices
+ *
+ * @param context Context
+ * @return LocationServices
+ */
+ public static LocationServices getLocationServices(@NonNull final Context context) {
+ if (instance == null) {
+ instance = new LocationServices(context.getApplicationContext());
}
-
- /**
- * Primary (singleton) access method for LocationServices
- *
- * @param context Context
- * @return LocationServices
- */
- public static LocationServices getLocationServices(@NonNull final Context context) {
- if (instance == null) {
- instance = new LocationServices(context.getApplicationContext());
- }
- return instance;
+ return instance;
+ }
+
+ /**
+ * Enabled / Disable GPS focused location tracking
+ *
+ * @param enableGPS true if GPS is to be enabled, false if GPS is to be disabled
+ */
+ public void toggleGPS(boolean enableGPS) {
+ if (!areLocationPermissionsGranted()) {
+ Timber.w("Location Permissions Not Granted Yet. Try again after requesting.");
+ return;
}
- /**
- * Enabled / Disable GPS focused location tracking
- *
- * @param enableGPS true if GPS is to be enabled, false if GPS is to be disabled
- */
- public void toggleGPS(boolean enableGPS) {
- if (!areLocationPermissionsGranted()) {
- Log.w(TAG, "Location Permissions Not Granted Yet. Try again after requesting.");
- return;
- }
-
- // Disconnect
- if (locationClient.isConnected()) {
- // Disconnect first to ensure that the new requests are GPS
- com.mapzen.android.lost.api.LocationServices.FusedLocationApi.removeLocationUpdates(this);
- locationClient.disconnect();
- }
-
- // Setup Fresh
- locationClient.connect();
- Location lastLocation = com.mapzen.android.lost.api.LocationServices.FusedLocationApi.getLastLocation();
- if (lastLocation != null) {
- this.lastLocation = lastLocation;
- }
-
- LocationRequest locationRequest;
-
- if (enableGPS) {
- // LocationRequest Tuned for GPS
- locationRequest = LocationRequest.create()
- .setFastestInterval(1000)
- .setSmallestDisplacement(3.0f)
- .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
-
- com.mapzen.android.lost.api.LocationServices.FusedLocationApi.requestLocationUpdates(locationRequest, this);
- } else {
- // LocationRequest Tuned for PASSIVE
- locationRequest = LocationRequest.create()
- .setFastestInterval(1000)
- .setSmallestDisplacement(3.0f)
- .setPriority(LocationRequest.PRIORITY_NO_POWER);
-
- com.mapzen.android.lost.api.LocationServices.FusedLocationApi.requestLocationUpdates(locationRequest, this);
- }
-
- isGPSEnabled = enableGPS;
+ // Disconnect
+ if (locationClient.isConnected()) {
+ // Disconnect first to ensure that the new requests are GPS
+ FusedLocationApi.removeLocationUpdates(locationClient, this);
+ locationClient.disconnect();
}
-
- /**
- * Returns if the GPS sensor is currently enabled
- *
- * @return active state of the GPS
- */
- public boolean isGPSEnabled() {
- return isGPSEnabled;
+ isGpsEnabled = enableGPS;
+
+ // Setup Fresh
+ locationClient.connect();
+ }
+
+ @Override
+ public void onConnected() {
+ //noinspection MissingPermission
+ Location lastLocation = FusedLocationApi.getLastLocation(locationClient);
+ if (lastLocation != null) {
+ this.lastLocation = lastLocation;
}
- /**
- * Called when the location has changed.
- *
- * @param location The updated location
- */
- @Override
- public void onLocationChanged(Location location) {
-// Log.d(TAG, "onLocationChanged()..." + location);
- this.lastLocation = location;
-
- // Update Listeners
- for (LocationListener listener : this.locationListeners) {
- listener.onLocationChanged(location);
- }
-
- // Update the Telemetry Receiver
- Intent locIntent = new Intent(TelemetryLocationReceiver.INTENT_STRING);
- locIntent.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
- context.sendBroadcast(locIntent);
+ LocationRequest locationRequest;
+
+ if (isGpsEnabled) {
+ // LocationRequest Tuned for GPS
+ locationRequest = LocationRequest.create()
+ .setFastestInterval(1000)
+ .setSmallestDisplacement(3.0f)
+ .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
+ //noinspection MissingPermission
+ FusedLocationApi.requestLocationUpdates(locationClient, locationRequest, this);
+ } else {
+ // LocationRequest Tuned for PASSIVE
+ locationRequest = LocationRequest.create()
+ .setFastestInterval(1000)
+ .setSmallestDisplacement(3.0f)
+ .setPriority(LocationRequest.PRIORITY_NO_POWER);
+ //noinspection MissingPermission
+ FusedLocationApi.requestLocationUpdates(locationClient, locationRequest, this);
}
-
- /**
- * Last known location
- *
- * @return Last known location data
- */
- public Location getLastLocation() {
- return lastLocation;
+ }
+
+ @Override
+ public void onConnectionSuspended() {
+ }
+
+ /**
+ * Returns if the GPS sensor is currently enabled
+ *
+ * @return active state of the GPS
+ */
+ public boolean isGpsEnabled() {
+ return isGpsEnabled;
+ }
+
+ /**
+ * Called when the location has changed.
+ *
+ * @param location The updated location
+ */
+ @Override
+ public void onLocationChanged(Location location) {
+ // Timber.d("onLocationChanged()..." + location);
+ this.lastLocation = location;
+
+ // Update Listeners
+ for (LocationListener listener : this.locationListeners) {
+ listener.onLocationChanged(location);
}
- /**
- * Registers a LocationListener to receive location updates
- *
- * @param locationListener LocationListener
- */
- public void addLocationListener(@NonNull LocationListener locationListener) {
- if (!this.locationListeners.contains(locationListener)) {
- this.locationListeners.add(locationListener);
- }
+ // Update the Telemetry Receiver
+ Intent locIntent = new Intent(TelemetryLocationReceiver.INTENT_STRING);
+ locIntent.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
+ LocalBroadcastManager.getInstance(context.getApplicationContext()).sendBroadcast(locIntent);
+ }
+
+ /**
+ * Last known location
+ *
+ * @return Last known location data
+ */
+ public Location getLastLocation() {
+ return lastLocation;
+ }
+
+ /**
+ * Registers a LocationListener to receive location updates
+ *
+ * @param locationListener LocationListener
+ */
+ public void addLocationListener(@NonNull LocationListener locationListener) {
+ if (!this.locationListeners.contains(locationListener)) {
+ this.locationListeners.add(locationListener);
}
-
- /**
- * Unregister a LocationListener to stop receiving location updates
- *
- * @param locationListener LocationListener to remove
- * @return True if LocationListener was found and removed, False if it was not
- */
- public boolean removeLocationListener(@NonNull LocationListener locationListener) {
- return this.locationListeners.remove(locationListener);
+ }
+
+ /**
+ * Unregister a LocationListener to stop receiving location updates
+ *
+ * @param locationListener LocationListener to remove
+ * @return True if LocationListener was found and removed, False if it was not
+ */
+ public boolean removeLocationListener(@NonNull LocationListener locationListener) {
+ return this.locationListeners.remove(locationListener);
+ }
+
+ /**
+ * Check status of Location Permissions
+ *
+ * @return True if granted to the app, False if not
+ */
+ public boolean areLocationPermissionsGranted() {
+ if ((ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED)
+ && (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED)) {
+ Timber.w("Location Permissions Not Granted Yet. Try again after requesting.");
+ return false;
}
+ return true;
+ }
- /**
- * Check status of Location Permissions
- * @return True if granted to the app, False if not
- */
- public boolean areLocationPermissionsGranted() {
- if ((ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) &&
- (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
- Log.w(TAG, "Location Permissions Not Granted Yet. Try again after requesting.");
- return false;
- }
- return true;
- }
+ @Override
+ public void onProviderDisabled(String provider) {
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ }
}
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
new file mode 100644
index 0000000000..05b37bc80d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java
@@ -0,0 +1,685 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.graphics.PointF;
+import android.graphics.RectF;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.util.LongSparseArray;
+
+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;
+import com.mapbox.mapboxsdk.annotations.Polygon;
+import com.mapbox.mapboxsdk.annotations.PolygonOptions;
+import com.mapbox.mapboxsdk.annotations.Polyline;
+import com.mapbox.mapboxsdk.annotations.PolylineOptions;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Responsible for managing and tracking state of Annotations linked to Map. All events related to
+ * annotations that occur on {@link MapboxMap} are forwarded to this class.
+ * <p>
+ * Responsible for referencing {@link InfoWindowManager} and {@link MarkerViewManager}.
+ * </p>
+ * <p>
+ * Exposes convenience methods to add/remove/update all subtypes of annotations found in
+ * com.mapbox.mapboxsdk.annotations.
+ * </p>
+ */
+class AnnotationManager {
+
+ 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> annotations = new LongSparseArray<>();
+ private final List<Marker> selectedMarkers = new ArrayList<>();
+
+ private MapboxMap mapboxMap;
+ private MapboxMap.OnMarkerClickListener onMarkerClickListener;
+
+ AnnotationManager(NativeMapView view, MapView mapView, MarkerViewManager markerViewManager) {
+ this.nativeMapView = view;
+ this.mapView = mapView;
+ this.iconManager = new IconManager(nativeMapView);
+ this.markerViewManager = markerViewManager;
+ if (view != null) {
+ // null checking needed for unit tests
+ nativeMapView.addOnMapChangedListener(markerViewManager);
+ }
+ }
+
+ // TODO refactor MapboxMap out for Projection and Transform
+ // Requires removing MapboxMap from Annotations by using Peer model from #6912
+ AnnotationManager bind(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ this.markerViewManager.bind(mapboxMap);
+ return this;
+ }
+
+ void update() {
+ markerViewManager.update();
+ infoWindowManager.update();
+ }
+
+ //
+ // Annotations
+ //
+
+ Annotation getAnnotation(long id) {
+ return annotations.get(id);
+ }
+
+ List<Annotation> getAnnotations() {
+ 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) {
+ if (annotation instanceof Marker) {
+ Marker marker = (Marker) annotation;
+ marker.hideInfoWindow();
+ if (marker instanceof MarkerView) {
+ markerViewManager.removeMarkerView((MarkerView) marker);
+ }
+ }
+ 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) {
+ 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();
+ if (marker instanceof MarkerView) {
+ markerViewManager.removeMarkerView((MarkerView) marker);
+ }
+ }
+ ids[i] = annotationList.get(i).getId();
+ }
+
+ if (nativeMapView != null) {
+ nativeMapView.removeAnnotations(ids);
+ }
+
+ for (long id : ids) {
+ annotations.remove(id);
+ }
+ }
+
+ void removeAnnotations() {
+ Annotation annotation;
+ int count = annotations.size();
+ long[] ids = new long[count];
+ for (int i = 0; i < count; 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);
+ }
+ }
+ }
+
+ if (nativeMapView != null) {
+ nativeMapView.removeAnnotations(ids);
+ }
+
+ annotations.clear();
+ }
+
+ //
+ // Markers
+ //
+
+ Marker addMarker(@NonNull BaseMarkerOptions markerOptions, @NonNull MapboxMap 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) {
+ 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);
+ }
+
+ if (markers.size() > 0) {
+ long[] ids = null;
+ if (nativeMapView != null) {
+ ids = nativeMapView.addMarkers(markers);
+ }
+
+ long id = 0;
+ Marker m;
+ for (int i = 0; i < markers.size(); i++) {
+ m = markers.get(i);
+ m.setMapboxMap(mapboxMap);
+ if (ids != null) {
+ id = ids[i];
+ } else {
+ //unit test
+ id++;
+ }
+ m.setId(id);
+ annotations.put(id, m);
+ }
+
+ }
+ }
+ return markers;
+ }
+
+ 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) {
+ final MarkerView marker = prepareViewMarker(markerOptions);
+
+ // add marker to map
+ marker.setMapboxMap(mapboxMap);
+ long id = nativeMapView.addMarker(marker);
+ marker.setId(id);
+ annotations.put(id, marker);
+
+ if (onMarkerViewAddedListener != null) {
+ markerViewManager.addOnMarkerViewAddedListener(marker, onMarkerViewAddedListener);
+ }
+ markerViewManager.setEnabled(true);
+ markerViewManager.setWaitingForRenderInvoke(true);
+ return marker;
+ }
+
+
+ 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;
+ }
+
+ private MarkerView prepareViewMarker(BaseMarkerViewOptions markerViewOptions) {
+ MarkerView marker = markerViewOptions.getMarker();
+ iconManager.loadIconForMarkerView(marker);
+ return marker;
+ }
+
+ void updateMarker(@NonNull Marker updatedMarker, @NonNull MapboxMap mapboxMap) {
+ if (updatedMarker == null) {
+ return;
+ }
+
+ if (updatedMarker.getId() == -1) {
+ return;
+ }
+
+ if (!(updatedMarker instanceof MarkerView)) {
+ iconManager.ensureIconLoaded(updatedMarker, mapboxMap);
+ }
+
+ nativeMapView.updateMarker(updatedMarker);
+
+ int index = annotations.indexOfKey(updatedMarker.getId());
+ if (index > -1) {
+ annotations.setValueAt(index, updatedMarker);
+ }
+ }
+
+ 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);
+ }
+ }
+ return markers;
+ }
+
+ void setOnMarkerClickListener(@Nullable MapboxMap.OnMarkerClickListener listener) {
+ onMarkerClickListener = listener;
+ }
+
+ void selectMarker(@NonNull Marker marker) {
+ if (selectedMarkers.contains(marker)) {
+ return;
+ }
+
+ // Need to deselect any currently selected annotation first
+ if (!infoWindowManager.isAllowConcurrentMultipleOpenInfoWindows()) {
+ deselectMarkers();
+ }
+
+ if (marker instanceof MarkerView) {
+ markerViewManager.select((MarkerView) marker, false);
+ markerViewManager.ensureInfoWindowOffset((MarkerView) marker);
+ }
+
+ if (infoWindowManager.isInfoWindowValidForMarker(marker) || infoWindowManager.getInfoWindowAdapter() != null) {
+ infoWindowManager.add(marker.showInfoWindow(mapboxMap, mapView));
+ }
+
+ // only add to selected markers if user didn't handle the click event themselves #3176
+ selectedMarkers.add(marker);
+ }
+
+ void deselectMarkers() {
+ if (selectedMarkers.isEmpty()) {
+ return;
+ }
+
+ for (Marker marker : selectedMarkers) {
+ if (marker.isInfoWindowShown()) {
+ marker.hideInfoWindow();
+ }
+
+ if (marker instanceof MarkerView) {
+ markerViewManager.deselect((MarkerView) marker, false);
+ }
+ }
+
+ // Removes all selected markers from the list
+ selectedMarkers.clear();
+ }
+
+ void deselectMarker(@NonNull Marker marker) {
+ if (!selectedMarkers.contains(marker)) {
+ return;
+ }
+
+ if (marker.isInfoWindowShown()) {
+ marker.hideInfoWindow();
+ }
+
+ if (marker instanceof MarkerView) {
+ markerViewManager.deselect((MarkerView) marker, false);
+ }
+
+ selectedMarkers.remove(marker);
+ }
+
+ List<Marker> getSelectedMarkers() {
+ return selectedMarkers;
+ }
+
+ List<Marker> getMarkersInRect(@NonNull RectF rectangle) {
+ // convert Rectangle to be density depedent
+ 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);
+ 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 = null;
+ if (nativeMapView != null) {
+ ids = nativeMapView.addPolygons(polygons);
+ }
+
+ long id = 0;
+ for (int i = 0; i < polygons.size(); i++) {
+ polygon = polygons.get(i);
+ polygon.setMapboxMap(mapboxMap);
+ if (ids != null) {
+ id = ids[i];
+ } else {
+ // unit test
+ id++;
+ }
+ polygon.setId(id);
+ annotations.put(id, polygon);
+ }
+ }
+ return polygons;
+ }
+
+ void updatePolygon(Polygon polygon) {
+ if (polygon == null) {
+ return;
+ }
+
+ if (polygon.getId() == -1) {
+ return;
+ }
+
+ nativeMapView.updatePolygon(polygon);
+
+ int index = annotations.indexOfKey(polygon.getId());
+ if (index > -1) {
+ annotations.setValueAt(index, 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);
+ 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 = null;
+ if (nativeMapView != null) {
+ ids = nativeMapView.addPolylines(polylines);
+ }
+
+ long id = 0;
+ Polyline p;
+
+ for (int i = 0; i < polylines.size(); i++) {
+ p = polylines.get(i);
+ p.setMapboxMap(mapboxMap);
+ if (ids != null) {
+ id = ids[i];
+ } else {
+ // unit test
+ id++;
+ }
+ p.setId(id);
+ annotations.put(id, p);
+ }
+ }
+ return polylines;
+ }
+
+ void updatePolyline(Polyline polyline) {
+ if (polyline == null) {
+ return;
+ }
+
+ if (polyline.getId() == -1) {
+ return;
+ }
+
+ nativeMapView.updatePolyline(polyline);
+
+ int index = annotations.indexOfKey(polyline.getId());
+ if (index > -1) {
+ annotations.setValueAt(index, 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;
+ }
+
+ MarkerViewManager getMarkerViewManager() {
+ return markerViewManager;
+ }
+
+ void adjustTopOffsetPixels(MapboxMap mapboxMap) {
+ int count = annotations.size();
+ for (int i = 0; i < count; i++) {
+ Annotation annotation = annotations.get(i);
+ if (annotation instanceof Marker) {
+ Marker marker = (Marker) annotation;
+ marker.setTopOffsetPixels(
+ iconManager.getTopOffsetPixelsForIcon(marker.getIcon()));
+ }
+ }
+
+ for (Marker marker : selectedMarkers) {
+ if (marker.isInfoWindowShown()) {
+ marker.hideInfoWindow();
+ marker.showInfoWindow(mapboxMap, mapView);
+ }
+ }
+ }
+
+ 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);
+ }
+ }
+ }
+
+ //
+ // Click event
+ //
+
+ boolean onTap(PointF tapPoint, float screenDensity) {
+ float toleranceSides = 4 * screenDensity;
+ float toleranceTopBottom = 10 * screenDensity;
+
+ RectF tapRect = new RectF(tapPoint.x - iconManager.getAverageIconWidth() / 2 - toleranceSides,
+ tapPoint.y - iconManager.getAverageIconHeight() / 2 - toleranceTopBottom,
+ tapPoint.x + iconManager.getAverageIconWidth() / 2 + toleranceSides,
+ tapPoint.y + iconManager.getAverageIconHeight() / 2 + toleranceTopBottom);
+
+ List<Marker> nearbyMarkers = getMarkersInRect(tapRect);
+ long newSelectedMarkerId = -1;
+
+ if (nearbyMarkers != null && nearbyMarkers.size() > 0) {
+ Collections.sort(nearbyMarkers);
+ for (Marker nearbyMarker : nearbyMarkers) {
+ boolean found = false;
+ for (Marker selectedMarker : selectedMarkers) {
+ if (selectedMarker.equals(nearbyMarker)) {
+ found = true;
+ }
+ }
+ if (!found) {
+ newSelectedMarkerId = nearbyMarker.getId();
+ break;
+ }
+ }
+ }
+
+ if (newSelectedMarkerId >= 0) {
+ List<Annotation> annotations = getAnnotations();
+ int count = annotations.size();
+ for (int i = 0; i < count; i++) {
+ Annotation annotation = annotations.get(i);
+ if (annotation instanceof Marker) {
+ if (annotation.getId() == newSelectedMarkerId) {
+ Marker marker = (Marker) annotation;
+ boolean handledDefaultClick = false;
+
+ if (marker instanceof MarkerView) {
+ handledDefaultClick = markerViewManager.onClickMarkerView((MarkerView) marker);
+ } else {
+ if (onMarkerClickListener != null) {
+ // end developer has provided a custom click listener
+ handledDefaultClick = onMarkerClickListener.onMarkerClick(marker);
+ }
+ }
+
+ if (annotation instanceof MarkerView) {
+ markerViewManager.onClickMarkerView((MarkerView) annotation);
+ } else {
+ if (!handledDefaultClick) {
+ // only select marker if user didn't handle the click event themselves
+ selectMarker(marker);
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassViewSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassViewSettings.java
deleted file mode 100644
index 3e1b14d641..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassViewSettings.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.mapbox.mapboxsdk.maps;
-
-/**
- * Settings for the overlain views of a MapboxMap. Used by UiSettings.
- */
-class CompassViewSettings extends ViewSettings{
-
- private boolean fadeFacingNorth = true;
-
- public CompassViewSettings() {
- super();
- }
-
- public boolean isFadeFacingNorth() {
- return fadeFacingNorth;
- }
-
- public void setFadeFacingNorth(boolean fadeFacingNorth) {
- this.fadeFacingNorth = fadeFacingNorth;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java
new file mode 100644
index 0000000000..006122a4e2
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java
@@ -0,0 +1,8 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.graphics.PointF;
+
+public interface FocalPointChangeListener {
+
+ void onFocalPointChanged(PointF pointF);
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java
new file mode 100644
index 0000000000..c9d81a88bc
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java
@@ -0,0 +1,158 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.graphics.Bitmap;
+import android.util.DisplayMetrics;
+
+import com.mapbox.mapboxsdk.annotations.Icon;
+import com.mapbox.mapboxsdk.annotations.IconFactory;
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerView;
+import com.mapbox.mapboxsdk.exceptions.IconBitmapChangedException;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Responsible for managing icons added to the Map.
+ * <p>
+ * Maintains a {@link List} of {@link Icon} and is responsible for initialising default markers and
+ * setting up {@link MarkerView} annotation ghosting.
+ * </p>
+ * <p>
+ * Keep track of icons added and the resulting average icon size. This is used internally by our
+ * gestures detection to calculate the size of a touch target.
+ * </p>
+ */
+class IconManager {
+
+ private NativeMapView nativeMapView;
+ private List<Icon> icons;
+
+ private int averageIconHeight;
+ private int averageIconWidth;
+
+ IconManager(NativeMapView nativeMapView) {
+ this.nativeMapView = nativeMapView;
+ this.icons = new ArrayList<>();
+ // load transparent icon for MarkerView to trace actual markers, see #6352
+ loadIcon(IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID, IconFactory.ICON_MARKERVIEW_BITMAP));
+ }
+
+ Icon loadIconForMarker(Marker marker) {
+ Icon icon = marker.getIcon();
+
+ // calculating average before adding
+ int iconSize = icons.size() + 1;
+
+ // TODO replace former if case with anchor implementation,
+ // current workaround for having extra pixels is diving height by 2
+ if (icon == null) {
+ icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarker();
+ Bitmap bitmap = icon.getBitmap();
+ averageIconHeight = averageIconHeight + (bitmap.getHeight() / 2 - averageIconHeight) / iconSize;
+ averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
+ marker.setIcon(icon);
+ } else {
+ Bitmap bitmap = icon.getBitmap();
+ averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize;
+ averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
+ }
+
+ if (!icons.contains(icon)) {
+ icons.add(icon);
+ loadIcon(icon);
+ } else {
+ Icon oldIcon = icons.get(icons.indexOf(icon));
+ if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
+ throw new IconBitmapChangedException();
+ }
+ }
+ return icon;
+ }
+
+ Icon loadIconForMarkerView(MarkerView marker) {
+ Icon icon = marker.getIcon();
+ int iconSize = icons.size() + 1;
+ if (icon == null) {
+ icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarkerView();
+ marker.setIcon(icon);
+ }
+ Bitmap bitmap = icon.getBitmap();
+ averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize;
+ averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
+ if (!icons.contains(icon)) {
+ icons.add(icon);
+ } else {
+ Icon oldIcon = icons.get(icons.indexOf(icon));
+ if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
+ throw new IconBitmapChangedException();
+ }
+ }
+ return icon;
+ }
+
+ int getTopOffsetPixelsForIcon(Icon icon) {
+ return (int) (nativeMapView.getTopOffsetPixelsForAnnotationSymbol(icon.getId()) * nativeMapView.getPixelRatio());
+ }
+
+ void loadIcon(Icon icon) {
+ Bitmap bitmap = icon.getBitmap();
+ String id = icon.getId();
+ if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
+ bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
+ }
+ ByteBuffer buffer = ByteBuffer.allocate(bitmap.getRowBytes() * bitmap.getHeight());
+ bitmap.copyPixelsToBuffer(buffer);
+
+ float density = bitmap.getDensity();
+ if (density == Bitmap.DENSITY_NONE) {
+ density = DisplayMetrics.DENSITY_DEFAULT;
+ }
+ float scale = density / DisplayMetrics.DENSITY_DEFAULT;
+ nativeMapView.addAnnotationIcon(
+ id,
+ bitmap.getWidth(),
+ bitmap.getHeight(),
+ scale, buffer.array());
+ }
+
+ void reloadIcons() {
+ int count = icons.size();
+ for (int i = 0; i < count; i++) {
+ Icon icon = icons.get(i);
+ loadIcon(icon);
+ }
+ }
+
+ void ensureIconLoaded(Marker marker, MapboxMap mapboxMap) {
+ Icon icon = marker.getIcon();
+ if (icon == null) {
+ icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarker();
+ marker.setIcon(icon);
+ }
+ if (!icons.contains(icon)) {
+ icons.add(icon);
+ loadIcon(icon);
+ } else {
+ Icon oldIcon = icons.get(icons.indexOf(icon));
+ if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
+ throw new IconBitmapChangedException();
+ }
+ }
+
+ // this seems to be a costly operation according to the profiler so I'm trying to save some calls
+ Marker previousMarker = marker.getId() != -1 ? (Marker) mapboxMap.getAnnotation(marker.getId()) : null;
+ if (previousMarker == null || previousMarker.getIcon() == null || previousMarker.getIcon() != marker.getIcon()) {
+ marker.setTopOffsetPixels(getTopOffsetPixelsForIcon(icon));
+ }
+ }
+
+ int getAverageIconHeight() {
+ return averageIconHeight;
+ }
+
+ int getAverageIconWidth() {
+ return averageIconWidth;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/InfoWindowManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/InfoWindowManager.java
new file mode 100644
index 0000000000..7599b6afa6
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/InfoWindowManager.java
@@ -0,0 +1,94 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+
+import com.mapbox.mapboxsdk.annotations.InfoWindow;
+import com.mapbox.mapboxsdk.annotations.Marker;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Responsible for managing InfoWindows shown on the Map.
+ * <p>
+ * Maintains a {@link List} of opened {@link InfoWindow} and tracks configurations as
+ * allowConcurrentMultipleInfoWindows which allows to have multiple {@link InfoWindow} open at the
+ * same time. Responsible for managing listeners as
+ * {@link com.mapbox.mapboxsdk.maps.MapboxMap.OnInfoWindowClickListener} and
+ * {@link com.mapbox.mapboxsdk.maps.MapboxMap.OnInfoWindowLongClickListener}.
+ * </p>
+ */
+class InfoWindowManager {
+
+ private List<InfoWindow> infoWindows;
+ private MapboxMap.InfoWindowAdapter infoWindowAdapter;
+ private boolean allowConcurrentMultipleInfoWindows;
+
+ private MapboxMap.OnInfoWindowClickListener onInfoWindowClickListener;
+ private MapboxMap.OnInfoWindowLongClickListener onInfoWindowLongClickListener;
+ private MapboxMap.OnInfoWindowCloseListener onInfoWindowCloseListener;
+
+ InfoWindowManager() {
+ this.infoWindows = new ArrayList<>();
+ }
+
+ void update() {
+ for (InfoWindow infoWindow : infoWindows) {
+ infoWindow.update();
+ }
+ }
+
+ void setInfoWindowAdapter(@Nullable MapboxMap.InfoWindowAdapter infoWindowAdapter) {
+ this.infoWindowAdapter = infoWindowAdapter;
+ }
+
+ MapboxMap.InfoWindowAdapter getInfoWindowAdapter() {
+ return infoWindowAdapter;
+ }
+
+ void setAllowConcurrentMultipleOpenInfoWindows(boolean allow) {
+ allowConcurrentMultipleInfoWindows = allow;
+ }
+
+ boolean isAllowConcurrentMultipleOpenInfoWindows() {
+ return allowConcurrentMultipleInfoWindows;
+ }
+
+ List<InfoWindow> getInfoWindows() {
+ return infoWindows;
+ }
+
+ boolean isInfoWindowValidForMarker(@NonNull Marker marker) {
+ return !TextUtils.isEmpty(marker.getTitle()) || !TextUtils.isEmpty(marker.getSnippet());
+ }
+
+ void setOnInfoWindowClickListener(@Nullable MapboxMap.OnInfoWindowClickListener listener) {
+ onInfoWindowClickListener = listener;
+ }
+
+ MapboxMap.OnInfoWindowClickListener getOnInfoWindowClickListener() {
+ return onInfoWindowClickListener;
+ }
+
+ void setOnInfoWindowLongClickListener(@Nullable MapboxMap.OnInfoWindowLongClickListener listener) {
+ onInfoWindowLongClickListener = listener;
+ }
+
+ MapboxMap.OnInfoWindowLongClickListener getOnInfoWindowLongClickListener() {
+ return onInfoWindowLongClickListener;
+ }
+
+ void setOnInfoWindowCloseListener(@Nullable MapboxMap.OnInfoWindowCloseListener listener) {
+ onInfoWindowCloseListener = listener;
+ }
+
+ MapboxMap.OnInfoWindowCloseListener getOnInfoWindowCloseListener() {
+ return onInfoWindowCloseListener;
+ }
+
+ public void add(InfoWindow infoWindow) {
+ infoWindows.add(infoWindow);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java
index 22f42c1d51..8b1ba7b771 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java
@@ -2,22 +2,14 @@ package com.mapbox.mapboxsdk.maps;
import android.app.Fragment;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.v4.content.ContextCompat;
-import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import com.mapbox.mapboxsdk.MapboxAccountManager;
-import com.mapbox.mapboxsdk.R;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
-import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException;
+import com.mapbox.mapboxsdk.utils.MapFragmentUtils;
/**
* Fragment wrapper around a map view.
@@ -35,194 +27,129 @@ import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException;
*/
public final class MapFragment extends Fragment {
- private MapView map;
- private OnMapReadyCallback onMapReadyCallback;
-
- /**
- * Creates a MapFragment instance
- *
- * @param mapboxMapOptions The configuration options to be used.
- * @return MapFragment created.
- */
- public static MapFragment newInstance(@Nullable MapboxMapOptions mapboxMapOptions) {
- MapFragment mapFragment = new MapFragment();
- Bundle bundle = new Bundle();
- bundle.putParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS, mapboxMapOptions);
- mapFragment.setArguments(bundle);
- return mapFragment;
- }
-
- /**
- * Creates the fragment view hierarchy.
- *
- * @param inflater Inflater used to inflate content.
- * @param container The parent layout for the map fragment.
- * @param savedInstanceState The saved instance state for the map fragment.
- * @return The view created
- */
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- super.onCreateView(inflater, container, savedInstanceState);
- Context context = inflater.getContext();
- MapboxMapOptions options = null;
-
- // Get bundle
- Bundle bundle = getArguments();
- if (bundle != null && bundle.containsKey(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS)) {
- options = bundle.getParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS);
- }
-
- // Assign an AccessToken if needed
- if (options == null || options.getAccessToken() == null) {
- String token = null;
- if (MapboxAccountManager.getInstance() != null) {
- token = MapboxAccountManager.getInstance().getAccessToken();
- } else {
- token = getToken(inflater.getContext());
- }
- if (TextUtils.isEmpty(token)) {
- throw new InvalidAccessTokenException();
- }
- if (options == null) {
- options = new MapboxMapOptions().accessToken(token);
- } else {
- options.accessToken(token);
- }
- }
-
- Drawable foregroundDrawable = options.getMyLocationForegroundDrawable();
- Drawable foregroundBearingDrawable = options.getMyLocationForegroundBearingDrawable();
- if (foregroundDrawable == null || foregroundBearingDrawable == null) {
- if (foregroundDrawable == null) {
- foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.ic_mylocationview_normal);
- }
- if (foregroundBearingDrawable == null) {
- foregroundBearingDrawable = ContextCompat.getDrawable(context, R.drawable.ic_mylocationview_bearing);
- }
- options.myLocationForegroundDrawables(foregroundDrawable, foregroundBearingDrawable);
- }
-
- if (options.getMyLocationBackgroundDrawable() == null) {
- options.myLocationBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.ic_mylocationview_background));
- }
-
- return map = new MapView(inflater.getContext(), options);
- }
-
- /**
- * <p>
- * Returns the Mapbox access token set in the app resources.
- * </p>
- * It will first search the application manifest for a {@link MapboxConstants#KEY_META_DATA_MANIFEST}
- * meta-data value. If not found it will then attempt to load the access token from the
- * {@code res/raw/token.txt} development file.
- *
- * @param context The {@link Context} of the {@link android.app.Activity} or {@link android.app.Fragment}.
- * @return The Mapbox access token or null if not found.
- * @see MapboxConstants#KEY_META_DATA_MANIFEST
- *
- * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)}
- */
- @Deprecated
- private String getToken(@NonNull Context context) {
- try {
- // read out AndroidManifest
- PackageManager packageManager = context.getPackageManager();
- ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
- String token = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_MANIFEST);
- if (token == null || token.isEmpty()) {
- throw new IllegalArgumentException();
- }
- return token;
- } catch (Exception e) {
- // use fallback on string resource, used for development
- int tokenResId = context.getResources().getIdentifier("mapbox_access_token", "string", context.getPackageName());
- return tokenResId != 0 ? context.getString(tokenResId) : null;
- }
- }
-
- /**
- * Called when the fragment view hierarchy is created.
- *
- * @param view The content view of the fragment
- * @param savedInstanceState THe saved instance state of the framgnt
- */
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- map.onCreate(savedInstanceState);
- }
-
- /**
- * Called when the fragment is visible for the users.
- */
- @Override
- public void onStart() {
- super.onStart();
- map.getMapAsync(onMapReadyCallback);
- }
-
- /**
- * Called when the fragment is ready to be interacted with.
- */
- @Override
- public void onResume() {
- super.onResume();
- map.onResume();
- }
-
- /**
- * Called when the fragment is pausing.
- */
- @Override
- public void onPause() {
- super.onPause();
- map.onPause();
- }
-
- /**
- * Called when the fragment state needs to be saved.
- *
- * @param outState The saved state
- */
- @Override
- public void onSaveInstanceState(@NonNull Bundle outState) {
- super.onSaveInstanceState(outState);
- map.onSaveInstanceState(outState);
- }
-
- /**
- * Called when the fragment is no longer visible for the user.
- */
- @Override
- public void onStop() {
- super.onStop();
- }
-
- /**
- * Called when the fragment receives onLowMemory call from the hosting Activity.
- */
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- map.onLowMemory();
- }
-
- /**
- * Called when the fragment is view hiearchy is being destroyed.
- */
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- map.onDestroy();
- }
-
- /**
- * Sets a callback object which will be triggered when the MapboxMap instance is ready to be used.
- *
- * @param onMapReadyCallback The callback to be invoked.
- */
- public void getMapAsync(@NonNull final OnMapReadyCallback onMapReadyCallback) {
- this.onMapReadyCallback = onMapReadyCallback;
- }
+ private MapView map;
+ private OnMapReadyCallback onMapReadyCallback;
+
+ /**
+ * Creates a default MapFragment instance
+ *
+ * @return MapFragment instantiated
+ */
+ public static MapFragment newInstance() {
+ return new MapFragment();
+ }
+
+ /**
+ * Creates a MapFragment instance
+ *
+ * @param mapboxMapOptions The configuration options to be used.
+ * @return MapFragment instantiated.
+ */
+ public static MapFragment newInstance(@Nullable MapboxMapOptions mapboxMapOptions) {
+ MapFragment mapFragment = new MapFragment();
+ mapFragment.setArguments(MapFragmentUtils.createFragmentArgs(mapboxMapOptions));
+ return mapFragment;
+ }
+
+ /**
+ * Creates the fragment view hierarchy.
+ *
+ * @param inflater Inflater used to inflate content.
+ * @param container The parent layout for the map fragment.
+ * @param savedInstanceState The saved instance state for the map fragment.
+ * @return The view created
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ super.onCreateView(inflater, container, savedInstanceState);
+ Context context = inflater.getContext();
+ return map = new MapView(context, MapFragmentUtils.resolveArgs(context, getArguments()));
+ }
+
+ /**
+ * Called when the fragment view hierarchy is created.
+ *
+ * @param view The content view of the fragment
+ * @param savedInstanceState THe saved instance state of the framgnt
+ */
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ map.onCreate(savedInstanceState);
+ }
+
+ /**
+ * Called when the fragment is visible for the users.
+ */
+ @Override
+ public void onStart() {
+ super.onStart();
+ map.onStart();
+ map.getMapAsync(onMapReadyCallback);
+ }
+
+ /**
+ * Called when the fragment is ready to be interacted with.
+ */
+ @Override
+ public void onResume() {
+ super.onResume();
+ map.onResume();
+ }
+
+ /**
+ * Called when the fragment is pausing.
+ */
+ @Override
+ public void onPause() {
+ super.onPause();
+ map.onPause();
+ }
+
+ /**
+ * Called when the fragment state needs to be saved.
+ *
+ * @param outState The saved state
+ */
+ @Override
+ public void onSaveInstanceState(@NonNull Bundle outState) {
+ super.onSaveInstanceState(outState);
+ map.onSaveInstanceState(outState);
+ }
+
+ /**
+ * Called when the fragment is no longer visible for the user.
+ */
+ @Override
+ public void onStop() {
+ super.onStop();
+ map.onStop();
+ }
+
+ /**
+ * Called when the fragment receives onLowMemory call from the hosting Activity.
+ */
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ map.onLowMemory();
+ }
+
+ /**
+ * Called when the fragment is view hiearchy is being destroyed.
+ */
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ map.onDestroy();
+ }
+
+ /**
+ * Sets a callback object which will be triggered when the MapboxMap instance is ready to be used.
+ *
+ * @param onMapReadyCallback The callback to be invoked.
+ */
+ public void getMapAsync(@NonNull final OnMapReadyCallback onMapReadyCallback) {
+ this.onMapReadyCallback = onMapReadyCallback;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
new file mode 100644
index 0000000000..11dee078ac
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
@@ -0,0 +1,657 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.content.Context;
+import android.graphics.PointF;
+import android.support.annotation.NonNull;
+import android.support.v4.view.GestureDetectorCompat;
+import android.support.v4.view.ScaleGestureDetectorCompat;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.view.ViewConfiguration;
+import android.widget.ZoomButtonsController;
+
+import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector;
+import com.almeros.android.multitouch.gesturedetectors.ShoveGestureDetector;
+import com.almeros.android.multitouch.gesturedetectors.TwoFingerGestureDetector;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.telemetry.MapboxEvent;
+import com.mapbox.mapboxsdk.utils.MathUtils;
+
+/**
+ * Manages gestures events on a MapView.
+ * <p>
+ * Relies on gesture detection code in almeros.android.multitouch.gesturedetectors.
+ * </p>
+ */
+final class MapGestureDetector {
+
+ private final Transform transform;
+ private final Projection projection;
+ private final UiSettings uiSettings;
+ private final TrackingSettings trackingSettings;
+ private final AnnotationManager annotationManager;
+
+ private final GestureDetectorCompat gestureDetector;
+ private final ScaleGestureDetector scaleGestureDetector;
+ private final RotateGestureDetector rotateGestureDetector;
+ private final ShoveGestureDetector shoveGestureDetector;
+
+ private MapboxMap.OnMapClickListener onMapClickListener;
+ private MapboxMap.OnMapLongClickListener onMapLongClickListener;
+ private MapboxMap.OnFlingListener onFlingListener;
+ private MapboxMap.OnScrollListener onScrollListener;
+
+ private PointF focalPoint;
+
+ private boolean twoTap = false;
+ private boolean zoomStarted = false;
+ private boolean dragStarted = false;
+ private boolean quickZoom = false;
+ private boolean scrollInProgress = false;
+ private boolean scaleGestureOccurred = false;
+
+ MapGestureDetector(Context context, Transform transform, Projection projection, UiSettings uiSettings,
+ TrackingSettings trackingSettings, AnnotationManager annotationManager) {
+ this.annotationManager = annotationManager;
+ this.transform = transform;
+ this.projection = projection;
+ this.uiSettings = uiSettings;
+ this.trackingSettings = trackingSettings;
+
+ // Touch gesture detectors
+ gestureDetector = new GestureDetectorCompat(context, new GestureListener());
+ gestureDetector.setIsLongpressEnabled(true);
+ scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener());
+ ScaleGestureDetectorCompat.setQuickScaleEnabled(scaleGestureDetector, true);
+ rotateGestureDetector = new RotateGestureDetector(context, new RotateGestureListener());
+ shoveGestureDetector = new ShoveGestureDetector(context, new ShoveGestureListener());
+ }
+
+ /**
+ * Set the gesture focal point.
+ * <p>
+ * this is the center point used for calculate transformations from gestures, value is
+ * overridden if end user provides his own through {@link UiSettings#setFocalPoint(PointF)}.
+ * </p>
+ *
+ * @param focalPoint the center point for gestures
+ */
+ void setFocalPoint(PointF focalPoint) {
+ if (focalPoint == null) {
+ // resetting focal point,
+ if (uiSettings.getFocalPoint() != null) {
+ // using user provided one to reset
+ focalPoint = uiSettings.getFocalPoint();
+ }
+ }
+ this.focalPoint = focalPoint;
+ }
+
+
+ /**
+ * Called when user touches the screen, all positions are absolute.
+ * <p>
+ * Forwards event to the related gesture detectors.
+ * </p>
+ *
+ * @param event the MotionEvent
+ * @return True if touch event is handled
+ */
+ boolean onTouchEvent(@NonNull MotionEvent event) {
+ // Check and ignore non touch or left clicks
+ if ((event.getButtonState() != 0) && (event.getButtonState() != MotionEvent.BUTTON_PRIMARY)) {
+ return false;
+ }
+
+ // Check two finger gestures first
+ rotateGestureDetector.onTouchEvent(event);
+ scaleGestureDetector.onTouchEvent(event);
+ shoveGestureDetector.onTouchEvent(event);
+
+ // Handle two finger tap
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ // First pointer down, reset scaleGestureOccurred, used to avoid triggering a fling after a scale gesture #7666
+ scaleGestureOccurred = false;
+ transform.setGestureInProgress(true);
+ break;
+
+ case MotionEvent.ACTION_POINTER_DOWN:
+ // Second pointer down
+ twoTap = event.getPointerCount() == 2
+ && uiSettings.isZoomGesturesEnabled();
+ if (twoTap) {
+ // Confirmed 2nd Finger Down
+ MapboxEvent.trackGestureEvent(projection,
+ MapboxEvent.GESTURE_TWO_FINGER_SINGLETAP, event.getX(), event.getY(), transform.getZoom());
+ }
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ // Second pointer up
+ break;
+
+ case MotionEvent.ACTION_UP:
+ // First pointer up
+ long tapInterval = event.getEventTime() - event.getDownTime();
+ boolean isTap = tapInterval <= ViewConfiguration.getTapTimeout();
+ boolean inProgress = rotateGestureDetector.isInProgress()
+ || scaleGestureDetector.isInProgress()
+ || shoveGestureDetector.isInProgress();
+
+ if (twoTap && isTap && !inProgress) {
+ if (focalPoint != null) {
+ transform.zoom(false, focalPoint.x, focalPoint.y);
+ } else {
+ PointF focalPoint = TwoFingerGestureDetector.determineFocalPoint(event);
+ transform.zoom(false, focalPoint.x, focalPoint.y);
+ }
+ twoTap = false;
+ return true;
+ }
+
+ // Scroll / Pan Has Stopped
+ if (scrollInProgress) {
+ MapboxEvent.trackGestureDragEndEvent(projection, event.getX(), event.getY(), transform.getZoom());
+ scrollInProgress = false;
+ }
+
+ twoTap = false;
+ transform.setGestureInProgress(false);
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ twoTap = false;
+ transform.setGestureInProgress(false);
+ break;
+ }
+
+ return gestureDetector.onTouchEvent(event);
+ }
+
+ /**
+ * Called for events that don't fit the other handlers.
+ * <p>
+ * Examples of such events are mouse scroll events, mouse moves, joystick & trackpad.
+ * </p>
+ *
+ * @param event The MotionEvent occured
+ * @return True is the event is handled
+ */
+ boolean onGenericMotionEvent(MotionEvent event) {
+ // Mouse events
+ //if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { // this is not available before API 18
+ if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == InputDevice.SOURCE_CLASS_POINTER) {
+ // Choose the action
+ switch (event.getActionMasked()) {
+ // Mouse scrolls
+ case MotionEvent.ACTION_SCROLL:
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Get the vertical scroll amount, one click = 1
+ float scrollDist = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+
+ // Scale the map by the appropriate power of two factor
+ transform.zoomBy(Math.pow(2.0, scrollDist), event.getX(), event.getY());
+
+ return true;
+
+ default:
+ // We are not interested in this event
+ return false;
+ }
+ }
+
+ // We are not interested in this event
+ return false;
+ }
+
+
+ /**
+ * Responsible for handling one finger gestures.
+ */
+ private class GestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
+
+ @Override
+ public boolean onDown(MotionEvent event) {
+ return true;
+ }
+
+ @Override
+ public boolean onDoubleTapEvent(MotionEvent e) {
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return false;
+ }
+
+ switch (e.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ break;
+ case MotionEvent.ACTION_MOVE:
+ break;
+ case MotionEvent.ACTION_UP:
+ if (quickZoom) {
+ // insert here?
+ quickZoom = false;
+ break;
+ }
+
+ // Single finger double tap
+ if (focalPoint != null) {
+ // User provided focal point
+ transform.zoom(true, focalPoint.x, focalPoint.y);
+ } else {
+ // Zoom in on gesture
+ transform.zoom(true, e.getX(), e.getY());
+ }
+ break;
+ }
+
+ MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_DOUBLETAP, e.getX(), e.getY(), transform.getZoom());
+
+ return true;
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent motionEvent) {
+ // Cancel any animation
+ transform.cancelTransitions();
+ return true;
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
+ PointF tapPoint = new PointF(motionEvent.getX(), motionEvent.getY());
+ boolean tapHandled = annotationManager.onTap(tapPoint, uiSettings.getPixelRatio());
+
+ if (!tapHandled) {
+ if (uiSettings.isDeselectMarkersOnTap()) {
+ // deselect any selected marker
+ annotationManager.deselectMarkers();
+ }
+
+ // notify app of map click
+ if (onMapClickListener != null) {
+ onMapClickListener.onMapClick(projection.fromScreenLocation(tapPoint));
+ }
+ }
+
+ MapboxEvent.trackGestureEvent(projection,
+ MapboxEvent.GESTURE_SINGLETAP, motionEvent.getX(), motionEvent.getY(), transform.getZoom());
+ return true;
+ }
+
+ @Override
+ public void onLongPress(MotionEvent motionEvent) {
+ if (onMapLongClickListener != null && !quickZoom) {
+ onMapLongClickListener.onMapLongClick(
+ projection.fromScreenLocation(new PointF(motionEvent.getX(), motionEvent.getY())));
+ }
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ if ((!trackingSettings.isScrollGestureCurrentlyEnabled()) || scaleGestureOccurred) {
+ // don't allow a fling is scroll is disabled
+ // and ignore when a scale gesture has occurred
+ return false;
+ }
+
+ float screenDensity = uiSettings.getPixelRatio();
+
+ // calculate velocity vector for xy dimensions, independent from screen size
+ double velocityXY = Math.hypot(velocityX / screenDensity, velocityY / screenDensity);
+ if (velocityXY < MapboxConstants.VELOCITY_THRESHOLD_IGNORE_FLING) {
+ // ignore short flings, these can occur when other gestures just have finished executing
+ return false;
+ }
+
+ trackingSettings.resetTrackingModesIfRequired(true, false);
+
+ // cancel any animation
+ transform.cancelTransitions();
+
+ // tilt results in a bigger translation, limiting input for #5281
+ double tilt = transform.getTilt();
+ double tiltFactor = 1 + ((tilt != 0) ? (tilt / 10) : 0); /* 1 -> 7 */
+ double offsetX = velocityX / tiltFactor / screenDensity;
+ double offsetY = velocityY / tiltFactor / screenDensity;
+
+ // calculate animation time based on displacement
+ long animationTime = (long) (velocityXY / 7 / tiltFactor + MapboxConstants.ANIMATION_DURATION_FLING_BASE);
+
+ // update transformation
+ transform.setGestureInProgress(true);
+ transform.moveBy(offsetX, offsetY, animationTime);
+ transform.setGestureInProgress(false);
+
+ if (onFlingListener != null) {
+ onFlingListener.onFling();
+ }
+
+ MapboxEvent.trackGestureEvent(projection,
+ MapboxEvent.GESTURE_PAN_START, e1.getX(), e1.getY(), transform.getZoom());
+ return true;
+ }
+
+ // Called for drags
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ if (!scrollInProgress) {
+ scrollInProgress = true;
+ }
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ if (dragStarted) {
+ return false;
+ }
+
+ // reset tracking if needed
+ trackingSettings.resetTrackingModesIfRequired(true, false);
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Scroll the map
+ transform.moveBy(-distanceX, -distanceY, 0 /*no duration*/);
+
+ if (onScrollListener != null) {
+ onScrollListener.onScroll();
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Responsible for handling two finger gestures and double-tap drag gestures.
+ */
+ private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+
+ long beginTime = 0;
+ float scaleFactor = 1.0f;
+
+ // Called when two fingers first touch the screen
+ @Override
+ public boolean onScaleBegin(ScaleGestureDetector detector) {
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return false;
+ }
+
+ scaleGestureOccurred = true;
+ beginTime = detector.getEventTime();
+ MapboxEvent.trackGestureEvent(projection,
+ MapboxEvent.GESTURE_PINCH_START, detector.getFocusX(), detector.getFocusY(), transform.getZoom());
+ return true;
+ }
+
+ // Called when fingers leave screen
+ @Override
+ public void onScaleEnd(ScaleGestureDetector detector) {
+ beginTime = 0;
+ scaleFactor = 1.0f;
+ zoomStarted = false;
+ }
+
+ // Called each time a finger moves
+ // Called for pinch zooms and quickzooms/quickscales
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return super.onScale(detector);
+ }
+
+ // If scale is large enough ignore a tap
+ scaleFactor *= detector.getScaleFactor();
+ if ((scaleFactor > 1.05f) || (scaleFactor < 0.95f)) {
+ zoomStarted = true;
+ }
+
+ // Ignore short touches in case it is a tap
+ // Also ignore small scales
+ long time = detector.getEventTime();
+ long interval = time - beginTime;
+ if (!zoomStarted && (interval <= ViewConfiguration.getTapTimeout())) {
+ return false;
+ }
+
+ if (!zoomStarted) {
+ return false;
+ }
+
+ if (dragStarted) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Gesture is a quickzoom if there aren't two fingers
+ quickZoom = !twoTap;
+
+ // make an assumption here; if the zoom center is specified by the gesture, it's NOT going
+ // to be in the center of the map. Therefore the zoom will translate the map center, so tracking
+ // should be disabled.
+
+ trackingSettings.resetTrackingModesIfRequired(!quickZoom, false);
+ // Scale the map
+ if (focalPoint != null) {
+ // arround user provided focal point
+ transform.zoomBy(detector.getScaleFactor(), focalPoint.x, focalPoint.y);
+ } else if (quickZoom) {
+ // clamp scale factors we feed to core #7514
+ float scaleFactor = MathUtils.clamp(detector.getScaleFactor(),
+ MapboxConstants.MINIMUM_SCALE_FACTOR_CLAMP,
+ MapboxConstants.MAXIMUM_SCALE_FACTOR_CLAMP);
+ // around center map
+ transform.zoomBy(scaleFactor, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+ } else {
+ // around gesture
+ transform.zoomBy(detector.getScaleFactor(), detector.getFocusX(), detector.getFocusY());
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Responsible for handling rotation gestures.
+ */
+ private class RotateGestureListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
+
+ long beginTime = 0;
+ float totalAngle = 0.0f;
+ boolean started = false;
+
+ // Called when two fingers first touch the screen
+ @Override
+ public boolean onRotateBegin(RotateGestureDetector detector) {
+ if (!trackingSettings.isRotateGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ beginTime = detector.getEventTime();
+ MapboxEvent.trackGestureEvent(projection,
+ MapboxEvent.GESTURE_ROTATION_START, detector.getFocusX(), detector.getFocusY(), transform.getZoom());
+ return true;
+ }
+
+ // Called when the fingers leave the screen
+ @Override
+ public void onRotateEnd(RotateGestureDetector detector) {
+ beginTime = 0;
+ totalAngle = 0.0f;
+ started = false;
+ }
+
+ // Called each time one of the two fingers moves
+ // Called for rotation
+ @Override
+ public boolean onRotate(RotateGestureDetector detector) {
+ if (!trackingSettings.isRotateGestureCurrentlyEnabled() || dragStarted) {
+ return false;
+ }
+
+ // If rotate is large enough ignore a tap
+ // Also is zoom already started, don't rotate
+ totalAngle += detector.getRotationDegreesDelta();
+ if (!zoomStarted && ((totalAngle > 20.0f) || (totalAngle < -20.0f))) {
+ started = true;
+ }
+
+ // Ignore short touches in case it is a tap
+ // Also ignore small rotate
+ long time = detector.getEventTime();
+ long interval = time - beginTime;
+ if (!started && (interval <= ViewConfiguration.getTapTimeout())) {
+ return false;
+ }
+
+ if (!started) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // rotation constitutes translation of anything except the center of
+ // rotation, so cancel both location and bearing tracking if required
+
+ trackingSettings.resetTrackingModesIfRequired(true, true);
+
+ // Get rotate value
+ double bearing = transform.getRawBearing();
+ bearing += detector.getRotationDegreesDelta();
+
+ // Rotate the map
+ if (focalPoint != null) {
+ // User provided focal point
+ transform.setBearing(bearing, focalPoint.x, focalPoint.y);
+ } else {
+ // around gesture
+ transform.setBearing(bearing, detector.getFocusX(), detector.getFocusY());
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Responsible for handling 2 finger shove gestures.
+ */
+ private class ShoveGestureListener implements ShoveGestureDetector.OnShoveGestureListener {
+
+ long beginTime = 0;
+ float totalDelta = 0.0f;
+ boolean started = false;
+
+ @Override
+ public boolean onShoveBegin(ShoveGestureDetector detector) {
+ if (!uiSettings.isTiltGesturesEnabled()) {
+ return false;
+ }
+
+ beginTime = detector.getEventTime();
+ MapboxEvent.trackGestureEvent(projection,
+ MapboxEvent.GESTURE_PITCH_START, detector.getFocusX(), detector.getFocusY(), transform.getZoom());
+ return true;
+ }
+
+ @Override
+ public void onShoveEnd(ShoveGestureDetector detector) {
+ beginTime = 0;
+ totalDelta = 0.0f;
+ started = false;
+ dragStarted = false;
+ }
+
+ @Override
+ public boolean onShove(ShoveGestureDetector detector) {
+ if (!uiSettings.isTiltGesturesEnabled()) {
+ return false;
+ }
+
+ // If tilt is large enough ignore a tap
+ // Also if zoom already started, don't tilt
+ totalDelta += detector.getShovePixelsDelta();
+ if (!zoomStarted && ((totalDelta > 10.0f) || (totalDelta < -10.0f))) {
+ started = true;
+ }
+
+ // Ignore short touches in case it is a tap
+ // Also ignore small tilt
+ long time = detector.getEventTime();
+ long interval = time - beginTime;
+ if (!started && (interval <= ViewConfiguration.getTapTimeout())) {
+ return false;
+ }
+
+ if (!started) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Get tilt value (scale and clamp)
+ double pitch = transform.getTilt();
+ pitch -= 0.1 * detector.getShovePixelsDelta();
+ pitch = Math.max(MapboxConstants.MINIMUM_TILT, Math.min(MapboxConstants.MAXIMUM_TILT, pitch));
+
+ // Tilt the map
+ transform.setTilt(pitch);
+
+ dragStarted = true;
+
+ return true;
+ }
+ }
+
+ // This class handles input events from the zoom control buttons
+ // Zoom controls allow single touch only devices to zoom in and out
+ private static class OnZoomListener implements ZoomButtonsController.OnZoomListener {
+
+ private UiSettings uiSettings;
+ private Transform transform;
+
+ OnZoomListener(UiSettings uiSettings, Transform transform) {
+ this.uiSettings = uiSettings;
+ this.transform = transform;
+ }
+
+ // Not used
+ @Override
+ public void onVisibilityChanged(boolean visible) {
+ // Ignore
+ }
+
+ // Called when user pushes a zoom button
+ @Override
+ public void onZoom(boolean zoomIn) {
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return;
+ }
+ transform.zoom(zoomIn);
+ }
+ }
+
+ void setOnMapClickListener(MapboxMap.OnMapClickListener onMapClickListener) {
+ this.onMapClickListener = onMapClickListener;
+ }
+
+ void setOnMapLongClickListener(MapboxMap.OnMapLongClickListener onMapLongClickListener) {
+ this.onMapLongClickListener = onMapLongClickListener;
+ }
+
+ void setOnFlingListener(MapboxMap.OnFlingListener onFlingListener) {
+ this.onFlingListener = onFlingListener;
+ }
+
+ void setOnScrollListener(MapboxMap.OnScrollListener onScrollListener) {
+ this.onScrollListener = onScrollListener;
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java
new file mode 100644
index 0000000000..c993cd3ec6
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java
@@ -0,0 +1,265 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+/**
+ * Manages key events on a MapView.
+ * <p>
+ * <ul>
+ * <li> Uses {@link Transform} to change the map state</li>
+ * <li> Uses {@link TrackingSettings} to verify validity of the current tracking mode.</li>
+ * <li> Uses {@link UiSettings} to verify validity of user restricted movement.</li>
+ * </ul>
+ * <p>
+ */
+final class MapKeyListener {
+
+ private final TrackingSettings trackingSettings;
+ private final Transform transform;
+ private final UiSettings uiSettings;
+
+ private TrackballLongPressTimeOut currentTrackballLongPressTimeOut;
+
+ MapKeyListener(@NonNull Transform transform, @NonNull TrackingSettings trackingSettings,
+ @NonNull UiSettings uiSettings) {
+ this.transform = transform;
+ this.trackingSettings = trackingSettings;
+ this.uiSettings = uiSettings;
+ }
+
+ /**
+ * Called when the user presses a key, alse called for repeated keys held down.
+ *
+ * @param keyCode the id of the pressed key
+ * @param event the related key event
+ * @return true if the wevent is handled
+ */
+ boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
+ // If the user has held the scroll key down for a while then accelerate
+ // the scroll speed
+ double scrollDist = event.getRepeatCount() >= 5 ? 50.0 : 10.0;
+
+ // Check which key was pressed via hardware/real key code
+ switch (keyCode) {
+ // Tell the system to track these keys for long presses on
+ // onKeyLongPress is fired
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ event.startTracking();
+ return true;
+
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Move left
+ transform.moveBy(scrollDist, 0.0, 0 /*no animation*/);
+ return true;
+
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Move right
+ transform.moveBy(-scrollDist, 0.0, 0 /*no animation*/);
+ return true;
+
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Move up
+ transform.moveBy(0.0, scrollDist, 0 /*no animation*/);
+ return true;
+
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Move down
+ transform.moveBy(0.0, -scrollDist, 0 /*no animation*/);
+ return true;
+
+ default:
+ // We are not interested in this key
+ return false;
+ }
+ }
+
+ /**
+ * Called when the user long presses a key that is being tracked.
+ *
+ * @param keyCode the id of the long pressed key
+ * @param event the related key event
+ * @return true if event is handled
+ */
+ boolean onKeyLongPress(int keyCode, KeyEvent event) {
+ // Check which key was pressed via hardware/real key code
+ switch (keyCode) {
+ // Tell the system to track these keys for long presses on
+ // onKeyLongPress is fired
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return false;
+ }
+
+ // Zoom out
+ transform.zoom(false, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+ return true;
+
+ default:
+ // We are not interested in this key
+ return false;
+ }
+ }
+
+ /**
+ * Called when the user releases a key.
+ *
+ * @param keyCode the id of the released key
+ * @param event the related key event
+ * @return true if the event is handled
+ */
+ boolean onKeyUp(int keyCode, KeyEvent event) {
+ // Check if the key action was canceled (used for virtual keyboards)
+ if (event.isCanceled()) {
+ return false;
+ }
+
+ // Check which key was pressed via hardware/real key code
+ // Note if keyboard does not have physical key (ie primary non-shifted
+ // key) then it will not appear here
+ // Must use the key character map as physical to character is not
+ // fixed/guaranteed
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return false;
+ }
+
+ // Zoom in
+ transform.zoom(true, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+ return true;
+ }
+
+ // We are not interested in this key
+ return false;
+ }
+
+ /**
+ * Called for trackball events, all motions are relative in device specific units.
+ *
+ * @param event the related motion event
+ * @return true if the event is handled
+ */
+ boolean onTrackballEvent(MotionEvent event) {
+ // Choose the action
+ switch (event.getActionMasked()) {
+ // The trackball was rotated
+ case MotionEvent.ACTION_MOVE:
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Scroll the map
+ transform.moveBy(-10.0 * event.getX(), -10.0 * event.getY(), 0 /*no animation*/);
+ return true;
+
+ // Trackball was pushed in so start tracking and tell system we are
+ // interested
+ // We will then get the up action
+ case MotionEvent.ACTION_DOWN:
+ // Set up a delayed callback to check if trackball is still
+ // After waiting the system long press time out
+ if (currentTrackballLongPressTimeOut != null) {
+ currentTrackballLongPressTimeOut.cancel();
+ currentTrackballLongPressTimeOut = null;
+ }
+ currentTrackballLongPressTimeOut = new TrackballLongPressTimeOut();
+ new Handler().postDelayed(currentTrackballLongPressTimeOut,
+ ViewConfiguration.getLongPressTimeout());
+ return true;
+
+ // Trackball was released
+ case MotionEvent.ACTION_UP:
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return false;
+ }
+
+ // Only handle if we have not already long pressed
+ if (currentTrackballLongPressTimeOut != null) {
+ // Zoom in
+ transform.zoom(true, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+ }
+ return true;
+
+ // Trackball was cancelled
+ case MotionEvent.ACTION_CANCEL:
+ if (currentTrackballLongPressTimeOut != null) {
+ currentTrackballLongPressTimeOut.cancel();
+ currentTrackballLongPressTimeOut = null;
+ }
+ return true;
+
+ default:
+ // We are not interested in this event
+ return false;
+ }
+ }
+
+ /**
+ * This class implements the trackball long press time out callback
+ */
+ private class TrackballLongPressTimeOut implements Runnable {
+
+ // Track if we have been cancelled
+ private boolean cancelled;
+
+ TrackballLongPressTimeOut() {
+ cancelled = false;
+ }
+
+ // Cancel the timeout
+ public void cancel() {
+ cancelled = true;
+ }
+
+ // Called when long press time out expires
+ @Override
+ public void run() {
+ // Check if the trackball is still pressed
+ if (!cancelled) {
+ // Zoom out
+ transform.zoom(false, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+
+ // Ensure the up action is not run
+ currentTrackballLongPressTimeOut = null;
+ }
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
index 32b327e8d0..3cb074d209 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
@@ -1,7 +1,5 @@
package com.mapbox.mapboxsdk.maps;
-import android.Manifest;
-import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.app.Fragment;
@@ -10,90 +8,51 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.PointF;
-import android.graphics.RectF;
import android.graphics.SurfaceTexture;
-import android.location.Location;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.CallSuper;
-import android.support.annotation.FloatRange;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
-import android.support.v4.content.ContextCompat;
-import android.support.v4.view.GestureDetectorCompat;
-import android.support.v4.view.ScaleGestureDetectorCompat;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.GestureDetector;
-import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
-import android.widget.ZoomButtonsController;
-import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector;
-import com.almeros.android.multitouch.gesturedetectors.ShoveGestureDetector;
-import com.almeros.android.multitouch.gesturedetectors.TwoFingerGestureDetector;
-import com.mapbox.mapboxsdk.MapboxAccountManager;
+import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.R;
-import com.mapbox.mapboxsdk.annotations.Annotation;
-import com.mapbox.mapboxsdk.annotations.Icon;
-import com.mapbox.mapboxsdk.annotations.IconFactory;
-import com.mapbox.mapboxsdk.annotations.InfoWindow;
-import com.mapbox.mapboxsdk.annotations.Marker;
-import com.mapbox.mapboxsdk.annotations.MarkerView;
-import com.mapbox.mapboxsdk.annotations.Polygon;
-import com.mapbox.mapboxsdk.annotations.Polyline;
+import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
-import com.mapbox.mapboxsdk.constants.MyBearingTracking;
-import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.constants.Style;
-import com.mapbox.mapboxsdk.exceptions.IconBitmapChangedException;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.location.LocationListener;
-import com.mapbox.mapboxsdk.location.LocationServices;
import com.mapbox.mapboxsdk.maps.widgets.CompassView;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
import com.mapbox.mapboxsdk.telemetry.MapboxEvent;
import com.mapbox.mapboxsdk.telemetry.MapboxEventManager;
-import com.mapbox.mapboxsdk.utils.ColorUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
/**
* <p>
@@ -111,3090 +70,946 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/
public class MapView extends FrameLayout {
- private MapboxMap mapboxMap;
- private boolean initialLoad;
- private boolean destroyed;
-
- private List<Icon> icons;
- private int averageIconHeight;
- private int averageIconWidth;
-
- private NativeMapView nativeMapView;
- private boolean hasSurface = false;
-
- private ViewGroup markerViewContainer;
- private CompassView compassView;
- private ImageView logoView;
- private ImageView attributionsView;
- private MyLocationView myLocationView;
- private LocationListener myLocationListener;
-
- private Projection projection;
-
- private CopyOnWriteArrayList<OnMapChangedListener> onMapChangedListener;
- private ZoomButtonsController zoomButtonsController;
- private ConnectivityReceiver connectivityReceiver;
- private float screenDensity = 1.0f;
-
- private TrackballLongPressTimeOut currentTrackballLongPressTimeOut;
- private GestureDetectorCompat gestureDetector;
- private ScaleGestureDetector scaleGestureDetector;
- private RotateGestureDetector rotateGestureDetector;
- private ShoveGestureDetector shoveGestureDetector;
- private boolean twoTap = false;
- private boolean zoomStarted = false;
- private boolean dragStarted = false;
- private boolean quickZoom = false;
- private boolean scrollInProgress = false;
-
- private int contentPaddingLeft;
- private int contentPaddingTop;
- private int contentPaddingRight;
- private int contentPaddingBottom;
-
- private PointF focalPoint;
-
- private String styleUrl = Style.MAPBOX_STREETS;
- private boolean styleWasSet = false;
-
- private List<OnMapReadyCallback> onMapReadyCallbackList;
- private SnapshotRequest snapshotRequest;
-
- @UiThread
- public MapView(@NonNull Context context) {
- super(context);
- initialize(context, MapboxMapOptions.createFromAttributes(context, null));
- }
-
- @UiThread
- public MapView(@NonNull Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- initialize(context, MapboxMapOptions.createFromAttributes(context, attrs));
- }
-
- @UiThread
- public MapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- initialize(context, MapboxMapOptions.createFromAttributes(context, attrs));
- }
-
- @UiThread
- public MapView(@NonNull Context context, @Nullable MapboxMapOptions options) {
- super(context);
- initialize(context, options);
- }
-
- private void initialize(@NonNull Context context, @NonNull MapboxMapOptions options) {
- if (isInEditMode()) {
- // if we are in an editor mode we show an image of a map
- LayoutInflater.from(context).inflate(R.layout.mapview_preview, this);
- return;
- }
-
- initialLoad = true;
- onMapReadyCallbackList = new ArrayList<>();
- onMapChangedListener = new CopyOnWriteArrayList<>();
- mapboxMap = new MapboxMap(this);
- projection = mapboxMap.getProjection();
-
- icons = new ArrayList<>();
- View view = LayoutInflater.from(context).inflate(R.layout.mapview_internal, this);
- setWillNotDraw(false);
-
- if (options.getTextureMode()) {
- TextureView textureView = new TextureView(context);
- textureView.setSurfaceTextureListener(new SurfaceTextureListener());
- addView(textureView, 0);
- } else {
- SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
- surfaceView.getHolder().addCallback(new SurfaceCallback());
- surfaceView.setVisibility(View.VISIBLE);
- }
-
- nativeMapView = new NativeMapView(this);
-
- // load transparent icon for MarkerView to trace actual markers, see #6352
- loadIcon(IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID, IconFactory.ICON_MARKERVIEW_BITMAP));
-
- // Ensure this view is interactable
- setClickable(true);
- setLongClickable(true);
- setFocusable(true);
- setFocusableInTouchMode(true);
- requestFocus();
-
- // Touch gesture detectors
- gestureDetector = new GestureDetectorCompat(context, new GestureListener());
- gestureDetector.setIsLongpressEnabled(true);
- scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener());
- ScaleGestureDetectorCompat.setQuickScaleEnabled(scaleGestureDetector, true);
- rotateGestureDetector = new RotateGestureDetector(context, new RotateGestureListener());
- shoveGestureDetector = new ShoveGestureDetector(context, new ShoveGestureListener());
-
- zoomButtonsController = new ZoomButtonsController(this);
- zoomButtonsController.setZoomSpeed(MapboxConstants.ANIMATION_DURATION);
- zoomButtonsController.setOnZoomListener(new OnZoomListener());
-
- // Connectivity
- onConnectivityChanged(isConnected());
-
- markerViewContainer = (ViewGroup) view.findViewById(R.id.markerViewContainer);
-
- myLocationView = (MyLocationView) view.findViewById(R.id.userLocationView);
- myLocationView.setMapboxMap(mapboxMap);
-
- compassView = (CompassView) view.findViewById(R.id.compassView);
- compassView.setMapboxMap(mapboxMap);
-
- logoView = (ImageView) view.findViewById(R.id.logoView);
-
- // Setup Attributions control
- attributionsView = (ImageView) view.findViewById(R.id.attributionView);
- attributionsView.setOnClickListener(new AttributionOnClickListener(this));
-
- screenDensity = context.getResources().getDisplayMetrics().density;
-
- setInitialState(options);
-
- // Shows the zoom controls
- if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) {
- mapboxMap.getUiSettings().setZoomControlsEnabled(true);
- }
- }
-
- private void setInitialState(MapboxMapOptions options) {
- mapboxMap.setDebugActive(options.getDebugActive());
-
- CameraPosition position = options.getCamera();
- if (position != null) {
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(position));
- myLocationView.setTilt(position.tilt);
- }
-
- // api base url
- String apiBaseUrl = options.getApiBaseUrl();
- if (!TextUtils.isEmpty(apiBaseUrl)) {
- setApiBaseUrl(apiBaseUrl);
- }
-
- // access token
- String accessToken = options.getAccessToken();
- if (!TextUtils.isEmpty(accessToken)) {
- mapboxMap.setAccessToken(accessToken);
- }
-
- // style url
- String style = options.getStyle();
- if (!TextUtils.isEmpty(style)) {
- styleUrl = style;
- }
-
- // MyLocationView
- MyLocationViewSettings myLocationViewSettings = mapboxMap.getMyLocationViewSettings();
- myLocationViewSettings.setForegroundDrawable(
- options.getMyLocationForegroundDrawable(), options.getMyLocationForegroundBearingDrawable());
- myLocationViewSettings.setForegroundTintColor(options.getMyLocationForegroundTintColor());
- myLocationViewSettings.setBackgroundDrawable(
- options.getMyLocationBackgroundDrawable(), options.getMyLocationBackgroundPadding());
- myLocationViewSettings.setBackgroundTintColor(options.getMyLocationBackgroundTintColor());
- myLocationViewSettings.setAccuracyAlpha(options.getMyLocationAccuracyAlpha());
- myLocationViewSettings.setAccuracyTintColor(options.getMyLocationAccuracyTintColor());
- mapboxMap.setMyLocationEnabled(options.getLocationEnabled());
-
- // Enable gestures
- UiSettings uiSettings = mapboxMap.getUiSettings();
- uiSettings.setZoomGesturesEnabled(options.getZoomGesturesEnabled());
- uiSettings.setZoomGestureChangeAllowed(options.getZoomGesturesEnabled());
- uiSettings.setScrollGesturesEnabled(options.getScrollGesturesEnabled());
- uiSettings.setScrollGestureChangeAllowed(options.getScrollGesturesEnabled());
- uiSettings.setRotateGesturesEnabled(options.getRotateGesturesEnabled());
- uiSettings.setRotateGestureChangeAllowed(options.getRotateGesturesEnabled());
- uiSettings.setTiltGesturesEnabled(options.getTiltGesturesEnabled());
- uiSettings.setTiltGestureChangeAllowed(options.getTiltGesturesEnabled());
-
- // Ui Controls
- uiSettings.setZoomControlsEnabled(options.getZoomControlsEnabled());
-
- // Zoom
- mapboxMap.setMaxZoom(options.getMaxZoom());
- mapboxMap.setMinZoom(options.getMinZoom());
-
- // Compass
- uiSettings.setCompassEnabled(options.getCompassEnabled());
- uiSettings.setCompassGravity(options.getCompassGravity());
- int[] compassMargins = options.getCompassMargins();
- if (compassMargins != null) {
- uiSettings.setCompassMargins(compassMargins[0], compassMargins[1], compassMargins[2], compassMargins[3]);
- } else {
- int tenDp = (int) getResources().getDimension(R.dimen.ten_dp);
- uiSettings.setCompassMargins(tenDp, tenDp, tenDp, tenDp);
- }
- uiSettings.setCompassFadeFacingNorth(options.getCompassFadeFacingNorth());
-
- // Logo
- uiSettings.setLogoEnabled(options.getLogoEnabled());
- uiSettings.setLogoGravity(options.getLogoGravity());
- int[] logoMargins = options.getLogoMargins();
- if (logoMargins != null) {
- uiSettings.setLogoMargins(logoMargins[0], logoMargins[1], logoMargins[2], logoMargins[3]);
- } else {
- int sixteenDp = (int) getResources().getDimension(R.dimen.sixteen_dp);
- uiSettings.setLogoMargins(sixteenDp, sixteenDp, sixteenDp, sixteenDp);
- }
-
- // Attribution
- uiSettings.setAttributionEnabled(options.getAttributionEnabled());
- uiSettings.setAttributionGravity(options.getAttributionGravity());
- int[] attributionMargins = options.getAttributionMargins();
- if (attributionMargins != null) {
- uiSettings.setAttributionMargins(attributionMargins[0], attributionMargins[1], attributionMargins[2], attributionMargins[3]);
- } else {
- Resources resources = getResources();
- int sevenDp = (int) resources.getDimension(R.dimen.seven_dp);
- int seventySixDp = (int) resources.getDimension(R.dimen.seventy_six_dp);
- uiSettings.setAttributionMargins(seventySixDp, sevenDp, sevenDp, sevenDp);
- }
-
- int attributionTintColor = options.getAttributionTintColor();
- uiSettings.setAttributionTintColor(attributionTintColor != -1
- ? attributionTintColor : ColorUtils.getPrimaryColor(getContext()));
- }
-
- //
- // Lifecycle events
- //
-
- /**
- * <p>
- * You must call this method from the parent's {@link android.app.Activity#onCreate(Bundle)} or
- * {@link android.app.Fragment#onCreate(Bundle)}.
- * </p>
- * You must set a valid access token with {@link MapView#setAccessToken(String)} before you this method
- * or an exception will be thrown.
- *
- * @param savedInstanceState Pass in the parent's savedInstanceState.
- * @see MapView#setAccessToken(String)
- */
- @UiThread
- public void onCreate(@Nullable Bundle savedInstanceState) {
- String accessToken = mapboxMap.getAccessToken();
- if (TextUtils.isEmpty(accessToken)) {
- accessToken = MapboxAccountManager.getInstance().getAccessToken();
- mapboxMap.setAccessToken(accessToken);
- } else {
- // user provided access token through xml attributes, need to start MapboxAccountManager
- MapboxAccountManager.start(getContext(), accessToken);
- }
-
- // Force a check for an access token
- MapboxAccountManager.validateAccessToken(accessToken);
-
- if (savedInstanceState != null && savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) {
-
- // Get previous camera position
- CameraPosition cameraPosition = savedInstanceState.getParcelable(MapboxConstants.STATE_CAMERA_POSITION);
- if (cameraPosition != null) {
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder(cameraPosition).build()));
- }
-
- UiSettings uiSettings = mapboxMap.getUiSettings();
- uiSettings.setZoomGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_ENABLED));
- uiSettings.setZoomGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_ENABLED_CHANGE));
- uiSettings.setScrollGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_SCROLL_ENABLED));
- uiSettings.setScrollGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_SCROLL_ENABLED_CHANGE));
- uiSettings.setRotateGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ROTATE_ENABLED));
- uiSettings.setRotateGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_ROTATE_ENABLED_CHANGE));
- uiSettings.setTiltGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_TILT_ENABLED));
- uiSettings.setTiltGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_TILT_ENABLED_CHANGE));
- uiSettings.setZoomControlsEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_CONTROLS_ENABLED));
-
- // Compass
- uiSettings.setCompassEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_COMPASS_ENABLED));
- uiSettings.setCompassGravity(savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_GRAVITY));
- uiSettings.setCompassMargins(savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_LEFT),
- savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_TOP),
- savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_RIGHT),
- savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM));
- uiSettings.setCompassFadeFacingNorth(savedInstanceState.getBoolean(MapboxConstants.STATE_COMPASS_FADE_WHEN_FACING_NORTH));
-
- // Logo
- uiSettings.setLogoEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_LOGO_ENABLED));
- uiSettings.setLogoGravity(savedInstanceState.getInt(MapboxConstants.STATE_LOGO_GRAVITY));
- uiSettings.setLogoMargins(savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_LEFT)
- , savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_TOP)
- , savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_RIGHT)
- , savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_BOTTOM));
-
- // Attribution
- uiSettings.setAttributionEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ATTRIBUTION_ENABLED));
- uiSettings.setAttributionGravity(savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_GRAVITY));
- uiSettings.setAttributionMargins(savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_LEFT)
- , savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_TOP)
- , savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_RIGHT)
- , savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_BOTTOM));
-
- mapboxMap.setDebugActive(savedInstanceState.getBoolean(MapboxConstants.STATE_DEBUG_ACTIVE));
- styleUrl = savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL);
-
- // User location
- try {
- mapboxMap.setMyLocationEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED));
- } catch (SecurityException ignore) {
- // User did not accept location permissions
- }
-
- TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
- //noinspection ResourceType
- trackingSettings.setMyLocationTrackingMode(
- savedInstanceState.getInt(MapboxConstants.STATE_MY_LOCATION_TRACKING_MODE, MyLocationTracking.TRACKING_NONE));
- //noinspection ResourceType
- trackingSettings.setMyBearingTrackingMode(
- savedInstanceState.getInt(MapboxConstants.STATE_MY_BEARING_TRACKING_MODE, MyBearingTracking.NONE));
- trackingSettings.setDismissLocationTrackingOnGesture(
- savedInstanceState.getBoolean(MapboxConstants.STATE_MY_LOCATION_TRACKING_DISMISS, true));
- trackingSettings.setDismissBearingTrackingOnGesture(
- savedInstanceState.getBoolean(MapboxConstants.STATE_MY_BEARING_TRACKING_DISMISS, true));
- } else if (savedInstanceState == null) {
- // Start Telemetry (authorization determined in initial MapboxEventManager constructor)
- Log.i(MapView.class.getCanonicalName(), "MapView start Telemetry...");
- MapboxEventManager eventManager = MapboxEventManager.getMapboxEventManager();
- eventManager.initialize(getContext(), getAccessToken());
- }
-
- // Initialize EGL
- nativeMapView.initializeDisplay();
- nativeMapView.initializeContext();
-
- // Add annotation deselection listener
- addOnMapChangedListener(new OnMapChangedListener() {
- @Override
- public void onMapChanged(@MapChange int change) {
- if (change == DID_FINISH_LOADING_STYLE && initialLoad) {
- initialLoad = false;
- reloadIcons();
- reloadMarkers();
- adjustTopOffsetPixels();
-
- // Notify listeners the map is ready
- if (onMapReadyCallbackList.size() > 0) {
- Iterator<OnMapReadyCallback> iterator = onMapReadyCallbackList.iterator();
- while (iterator.hasNext()) {
- OnMapReadyCallback callback = iterator.next();
- callback.onMapReady(mapboxMap);
- iterator.remove();
- }
- }
-
- // invalidate camera to update overlain views with correct tilt value
- invalidateCameraPosition();
-
- } else if (change == REGION_IS_CHANGING || change == REGION_DID_CHANGE || change == DID_FINISH_LOADING_MAP) {
- mapboxMap.getMarkerViewManager().scheduleViewMarkerInvalidation();
-
- compassView.update(getDirection());
- myLocationView.update();
- mapboxMap.getMarkerViewManager().update();
-
- for (InfoWindow infoWindow : mapboxMap.getInfoWindows()) {
- infoWindow.update();
- }
- }
-
- }
- });
-
- // Fire MapLoad
- if (savedInstanceState == null) {
- Hashtable<String, Object> evt = new Hashtable<>();
- evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_LOAD);
- evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate());
- MapboxEventManager.getMapboxEventManager().pushEvent(evt);
- }
- }
-
- /**
- * You must call this method from the parent's {@link android.app.Activity#onSaveInstanceState(Bundle)}
- * or {@link android.app.Fragment#onSaveInstanceState(Bundle)}.
- *
- * @param outState Pass in the parent's outState.
- */
-
- @UiThread
- public void onSaveInstanceState(@NonNull Bundle outState) {
- outState.putBoolean(MapboxConstants.STATE_HAS_SAVED_STATE, true);
- outState.putParcelable(MapboxConstants.STATE_CAMERA_POSITION, mapboxMap.getCameraPosition());
- outState.putBoolean(MapboxConstants.STATE_DEBUG_ACTIVE, mapboxMap.isDebugActive());
- outState.putString(MapboxConstants.STATE_STYLE_URL, styleUrl);
- outState.putBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED, mapboxMap.isMyLocationEnabled());
-
- // TrackingSettings
- TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
- outState.putInt(MapboxConstants.STATE_MY_LOCATION_TRACKING_MODE, trackingSettings.getMyLocationTrackingMode());
- outState.putInt(MapboxConstants.STATE_MY_BEARING_TRACKING_MODE, trackingSettings.getMyBearingTrackingMode());
- outState.putBoolean(MapboxConstants.STATE_MY_LOCATION_TRACKING_DISMISS, trackingSettings.isDismissLocationTrackingOnGesture());
- outState.putBoolean(MapboxConstants.STATE_MY_BEARING_TRACKING_DISMISS, trackingSettings.isDismissBearingTrackingOnGesture());
-
- // UiSettings
- UiSettings uiSettings = mapboxMap.getUiSettings();
- outState.putBoolean(MapboxConstants.STATE_ZOOM_ENABLED, uiSettings.isZoomGesturesEnabled());
- outState.putBoolean(MapboxConstants.STATE_ZOOM_ENABLED_CHANGE, uiSettings.isZoomGestureChangeAllowed());
- outState.putBoolean(MapboxConstants.STATE_SCROLL_ENABLED, uiSettings.isScrollGesturesEnabled());
- outState.putBoolean(MapboxConstants.STATE_SCROLL_ENABLED_CHANGE, uiSettings.isScrollGestureChangeAllowed());
- outState.putBoolean(MapboxConstants.STATE_ROTATE_ENABLED, uiSettings.isRotateGesturesEnabled());
- outState.putBoolean(MapboxConstants.STATE_ROTATE_ENABLED_CHANGE, uiSettings.isRotateGestureChangeAllowed());
- outState.putBoolean(MapboxConstants.STATE_TILT_ENABLED, uiSettings.isTiltGesturesEnabled());
- outState.putBoolean(MapboxConstants.STATE_TILT_ENABLED_CHANGE, uiSettings.isTiltGestureChangeAllowed());
- outState.putBoolean(MapboxConstants.STATE_ZOOM_CONTROLS_ENABLED, uiSettings.isZoomControlsEnabled());
-
- // UiSettings - Compass
- outState.putBoolean(MapboxConstants.STATE_COMPASS_ENABLED, uiSettings.isCompassEnabled());
- outState.putInt(MapboxConstants.STATE_COMPASS_GRAVITY, uiSettings.getCompassGravity());
- outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_LEFT, uiSettings.getCompassMarginLeft());
- outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_TOP, uiSettings.getCompassMarginTop());
- outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM, uiSettings.getCompassMarginBottom());
- outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_RIGHT, uiSettings.getCompassMarginRight());
- outState.putBoolean(MapboxConstants.STATE_COMPASS_FADE_WHEN_FACING_NORTH, uiSettings.isCompassFadeWhenFacingNorth());
-
- // UiSettings - Logo
- outState.putInt(MapboxConstants.STATE_LOGO_GRAVITY, uiSettings.getLogoGravity());
- outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_LEFT, uiSettings.getLogoMarginLeft());
- outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_TOP, uiSettings.getLogoMarginTop());
- outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_RIGHT, uiSettings.getLogoMarginRight());
- outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_BOTTOM, uiSettings.getLogoMarginBottom());
- outState.putBoolean(MapboxConstants.STATE_LOGO_ENABLED, uiSettings.isLogoEnabled());
-
- // UiSettings - Attribution
- outState.putInt(MapboxConstants.STATE_ATTRIBUTION_GRAVITY, uiSettings.getAttributionGravity());
- outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_LEFT, uiSettings.getAttributionMarginLeft());
- outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_TOP, uiSettings.getAttributionMarginTop());
- outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_RIGHT, uiSettings.getAttributionMarginRight());
- outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_BOTTOM, uiSettings.getAttributionMarginBottom());
- outState.putBoolean(MapboxConstants.STATE_ATTRIBUTION_ENABLED, uiSettings.isAttributionEnabled());
- }
-
- /**
- * You must call this method from the parent's {@link Activity#onDestroy()} or {@link Fragment#onDestroy()}.
- */
- @UiThread
- public void onDestroy() {
- destroyed = true;
- nativeMapView.terminateContext();
- nativeMapView.terminateDisplay();
- nativeMapView.destroySurface();
- nativeMapView.destroy();
- nativeMapView = null;
- }
-
- /**
- * You must call this method from the parent's {@link Activity#onPause()} or {@link Fragment#onPause()}.
- */
- @UiThread
- public void onPause() {
- // Unregister for connectivity changes
- if (connectivityReceiver != null) {
- getContext().unregisterReceiver(connectivityReceiver);
- connectivityReceiver = null;
- }
-
- myLocationView.onPause();
- }
-
- /**
- * You must call this method from the parent's {@link Activity#onResume()} or {@link Fragment#onResume()}.
- */
- @UiThread
- public void onResume() {
- // Register for connectivity changes
- connectivityReceiver = new ConnectivityReceiver();
- getContext().registerReceiver(connectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
-
- nativeMapView.update();
- myLocationView.onResume();
-
- // In case that no style was set or was loaded through MapboxMapOptions
- if (!styleWasSet) {
- setStyleUrl(styleUrl);
- }
- }
-
- void setFocalPoint(PointF focalPoint) {
- if (focalPoint == null) {
- // resetting focal point,
- UiSettings uiSettings = mapboxMap.getUiSettings();
- // need to validate if we need to reset focal point with user provided one
- if (uiSettings.getFocalPoint() != null) {
- focalPoint = uiSettings.getFocalPoint();
- }
- }
- this.focalPoint = focalPoint;
- }
-
- /**
- * You must call this method from the parent's {@link Activity#onLowMemory()} or {@link Fragment#onLowMemory()}.
- */
- @UiThread
- public void onLowMemory() {
- nativeMapView.onLowMemory();
- }
-
- // Called when debug mode is enabled to update a FPS counter
- // Called via JNI from NativeMapView
- // Forward to any listener
- protected void onFpsChanged(final double fps) {
- post(new Runnable() {
- @Override
- public void run() {
- MapboxMap.OnFpsChangedListener listener = mapboxMap.getOnFpsChangedListener();
- if (listener != null) {
- listener.onFpsChanged(fps);
- }
- }
- });
- }
-
- //
- // LatLng / CenterCoordinate
- //
-
- LatLng getLatLng() {
- return nativeMapView.getLatLng();
- }
-
- //
- // Pitch / Tilt
- //
-
- double getTilt() {
- return nativeMapView.getPitch();
- }
-
- void setTilt(Double pitch) {
- mapboxMap.getMarkerViewManager().setTilt(pitch.floatValue());
- myLocationView.setTilt(pitch);
- nativeMapView.setPitch(pitch, 0);
- }
-
-
- //
- // Direction
- //
-
- double getDirection() {
- if (destroyed) {
- return 0;
- }
-
- double direction = -nativeMapView.getBearing();
-
- while (direction > 360) {
- direction -= 360;
- }
- while (direction < 0) {
- direction += 360;
- }
-
- return direction;
- }
-
- void setDirection(@FloatRange(from = MapboxConstants.MINIMUM_DIRECTION, to = MapboxConstants.MAXIMUM_DIRECTION) double direction) {
- if (destroyed) {
- return;
- }
- setDirection(direction, false);
- }
-
- void setDirection(@FloatRange(from = MapboxConstants.MINIMUM_DIRECTION, to = MapboxConstants.MAXIMUM_DIRECTION) double direction, boolean animated) {
- if (destroyed) {
- return;
- }
- long duration = animated ? MapboxConstants.ANIMATION_DURATION : 0;
- nativeMapView.cancelTransitions();
- // Out of range directions are normalised in setBearing
- nativeMapView.setBearing(-direction, duration);
- }
-
- void resetNorth() {
- if (destroyed) {
- return;
- }
- myLocationView.setBearing(0);
- nativeMapView.cancelTransitions();
- nativeMapView.resetNorth();
- }
-
- //
- // Content padding
- //
-
- int getContentPaddingLeft() {
- return contentPaddingLeft;
- }
-
- int getContentPaddingTop() {
- return contentPaddingTop;
- }
-
- int getContentPaddingRight() {
- return contentPaddingRight;
- }
-
- int getContentPaddingBottom() {
- return contentPaddingBottom;
- }
-
- int getContentWidth() {
- return getWidth() - contentPaddingLeft - contentPaddingRight;
- }
-
- int getContentHeight() {
- return getHeight() - contentPaddingBottom - contentPaddingTop;
- }
-
- //
- // Zoom
- //
-
- double getZoom() {
- if (destroyed) {
- return 0;
- }
- return nativeMapView.getZoom();
- }
-
- void setMinZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) {
- if (destroyed) {
- return;
- }
- nativeMapView.setMinZoom(minZoom);
- }
-
- double getMinZoom() {
- if (destroyed) {
- return 0;
- }
- return nativeMapView.getMinZoom();
- }
-
- void setMaxZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) {
- if (destroyed) {
- return;
- }
- nativeMapView.setMaxZoom(maxZoom);
- }
-
- double getMaxZoom() {
- if (destroyed) {
- return 0;
- }
- return nativeMapView.getMaxZoom();
- }
-
- // Zoom in or out
- private void zoom(boolean zoomIn) {
- zoom(zoomIn, -1.0f, -1.0f);
- }
-
- private void zoom(boolean zoomIn, float x, float y) {
- // Cancel any animation
- nativeMapView.cancelTransitions();
-
- if (zoomIn) {
- nativeMapView.scaleBy(2.0, x / screenDensity, y / screenDensity, MapboxConstants.ANIMATION_DURATION);
- } else {
- nativeMapView.scaleBy(0.5, x / screenDensity, y / screenDensity, MapboxConstants.ANIMATION_DURATION);
- }
-
- // work around to invalidate camera position
- postDelayed(new ZoomInvalidator(mapboxMap), MapboxConstants.ANIMATION_DURATION);
- }
-
- //
- // Debug
- //
-
- boolean isDebugActive() {
- if (destroyed) {
- return false;
- }
- return nativeMapView.getDebug();
- }
-
- void setDebugActive(boolean debugActive) {
- if (destroyed) {
- return;
- }
- nativeMapView.setDebug(debugActive);
- }
-
- void cycleDebugOptions() {
- if (destroyed) {
- return;
- }
- nativeMapView.cycleDebugOptions();
- }
-
- //
- // Styling
- //
-
- /**
- * <p>
- * Loads a new map style from the specified URL.
- * </p>
- * {@code url} can take the following forms:
- * <ul>
- * <li>{@code Style.*}: load one of the bundled styles in {@link Style}.</li>
- * <li>{@code mapbox://styles/<user>/<style>}:
- * retrieves the style from a <a href="https://www.mapbox.com/account/">Mapbox account.</a>
- * {@code user} is your username. {@code style} is the ID of your custom
- * style created in <a href="https://www.mapbox.com/studio">Mapbox Studio</a>.</li>
- * <li>{@code http://...} or {@code https://...}:
- * retrieves the style over the Internet from any web server.</li>
- * <li>{@code asset://...}:
- * reads the style from the APK {@code assets/} directory.
- * This is used to load a style bundled with your app.</li>
- * <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li>
- * </ul>
- * <p>
- * This method is asynchronous and will return immediately before the style finishes loading.
- * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event.
- * </p>
- * If the style fails to load or an invalid style URL is set, the map view will become blank.
- * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be sent.
- *
- * @param url The URL of the map style
- * @see Style
- */
- public void setStyleUrl(@NonNull String url) {
- if (destroyed) {
- return;
- }
-
- // stopgap for https://github.com/mapbox/mapbox-gl-native/issues/6242
- if (TextUtils.isEmpty(nativeMapView.getAccessToken())) {
- setAccessToken(MapboxAccountManager.getInstance().getAccessToken());
- }
-
- styleUrl = url;
- nativeMapView.setStyleUrl(url);
- styleWasSet = true;
- }
-
- /**
- * <p>
- * Loads a new map style from the specified bundled style.
- * </p>
- * <p>
- * This method is asynchronous and will return immediately before the style finishes loading.
- * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event.
- * </p>
- * If the style fails to load or an invalid style URL is set, the map view will become blank.
- * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be sent.
- *
- * @param style The bundled style. Accepts one of the values from {@link Style}.
- * @see Style
- */
- @UiThread
- public void setStyle(@Style.StyleUrl String style) {
- setStyleUrl(style);
- }
-
- /**
- * <p>
- * Returns the map style currently displayed in the map view.
- * </p>
- * If the default style is currently displayed, a URL will be returned instead of null.
- *
- * @return The URL of the map style.
- */
- @UiThread
- @NonNull
- public String getStyleUrl() {
- return styleUrl;
- }
-
- //
- // API Base URL
- //
-
- @UiThread
- void setApiBaseUrl(@NonNull String baseUrl) {
- nativeMapView.setApiBaseUrl(baseUrl);
- }
-
- //
- // Access token
- //
-
- /**
- * <p>
- * DEPRECATED @see MapboxAccountManager#start(String)
- * </p>
- * <p>
- * Sets the current Mapbox access token used to load map styles and tiles.
- * </p>
- * <p>
- * You must set a valid access token before you call {@link MapView#onCreate(Bundle)}
- * or an exception will be thrown.
- * </p>
- *
- * @param accessToken Your public Mapbox access token.
- * @see MapView#onCreate(Bundle)
- * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)}
- */
- @Deprecated
- @UiThread
- public void setAccessToken(@NonNull String accessToken) {
- if (destroyed) {
- return;
- }
- // validateAccessToken does the null check
- if (!TextUtils.isEmpty(accessToken)) {
- accessToken = accessToken.trim();
- }
- MapboxAccountManager.validateAccessToken(accessToken);
- nativeMapView.setAccessToken(accessToken);
- }
-
- /**
- * <p>
- * DEPRECATED @see MapboxAccountManager#getAccessToken()
- * </p>
- * <p>
- * Returns the current Mapbox access token used to load map styles and tiles.
- * </p>
- *
- * @return The current Mapbox access token.
- * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#getAccessToken()}
- */
- @Deprecated
- @UiThread
- @Nullable
- public String getAccessToken() {
- if (destroyed) {
- return "";
- }
- return nativeMapView.getAccessToken();
- }
-
- //
- // Projection
- //
-
- /*
- * Internal use only, use Projection#fromScreenLocation instead
- */
- LatLng fromNativeScreenLocation(@NonNull PointF point) {
- if (destroyed) {
- return new LatLng();
- }
- return nativeMapView.latLngForPixel(point);
- }
-
- /*
- * Internal use only, use Projection#toScreenLocation instead.
- */
- PointF toNativeScreenLocation(@NonNull LatLng location) {
- if (destroyed || location == null) {
- return new PointF();
- }
- return nativeMapView.pixelForLatLng(location);
- }
-
- //
- // Annotations
- //
-
- Icon loadIconForMarker(Marker marker) {
- Icon icon = marker.getIcon();
-
- // calculating average before adding
- int iconSize = icons.size() + 1;
-
- // TODO replace former if case with anchor implementation,
- // current workaround for having extra pixels is diving height by 2
- if (icon == null) {
- icon = IconFactory.getInstance(getContext()).defaultMarker();
- Bitmap bitmap = icon.getBitmap();
- averageIconHeight = averageIconHeight + (bitmap.getHeight() / 2 - averageIconHeight) / iconSize;
- averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
- marker.setIcon(icon);
- } else {
- Bitmap bitmap = icon.getBitmap();
- averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize;
- averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
- }
-
- if (!icons.contains(icon)) {
- icons.add(icon);
- loadIcon(icon);
- } else {
- Icon oldIcon = icons.get(icons.indexOf(icon));
- if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
- throw new IconBitmapChangedException();
- }
- }
- return icon;
- }
-
- Icon loadIconForMarkerView(MarkerView marker) {
- Icon icon = marker.getIcon();
- int iconSize = icons.size() + 1;
- if (icon == null) {
- icon = IconFactory.getInstance(getContext()).defaultMarkerView();
- marker.setIcon(icon);
- }
- Bitmap bitmap = icon.getBitmap();
- averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize;
- averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
- if (!icons.contains(icon)) {
- icons.add(icon);
- } else {
- Icon oldIcon = icons.get(icons.indexOf(icon));
- if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
- throw new IconBitmapChangedException();
- }
- }
- return icon;
- }
-
- void loadIcon(Icon icon) {
- if (destroyed) {
- return;
- }
- Bitmap bitmap = icon.getBitmap();
- String id = icon.getId();
- if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
- bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
- }
- ByteBuffer buffer = ByteBuffer.allocate(bitmap.getRowBytes() * bitmap.getHeight());
- bitmap.copyPixelsToBuffer(buffer);
-
- float density = bitmap.getDensity();
- if (density == Bitmap.DENSITY_NONE) {
- density = DisplayMetrics.DENSITY_DEFAULT;
- }
- float scale = density / DisplayMetrics.DENSITY_DEFAULT;
- nativeMapView.addAnnotationIcon(
- id,
- bitmap.getWidth(),
- bitmap.getHeight(),
- scale, buffer.array());
- }
-
- void reloadIcons() {
- int count = icons.size();
- for (int i = 0; i < count; i++) {
- Icon icon = icons.get(i);
- loadIcon(icon);
- }
- }
-
- void updateMarker(@NonNull Marker updatedMarker) {
- if (destroyed) {
- return;
- }
- if (updatedMarker == null) {
- Log.w(MapboxConstants.TAG, "marker was null, doing nothing");
- return;
- }
-
- if (updatedMarker.getId() == -1) {
- Log.w(MapboxConstants.TAG, "marker has an id of -1, possibly was not added yet, doing nothing");
- return;
- }
-
- if (!(updatedMarker instanceof MarkerView)) {
- ensureIconLoaded(updatedMarker);
- }
-
- nativeMapView.updateMarker(updatedMarker);
- }
-
-
- void updatePolygon(Polygon polygon) {
- if (destroyed) {
- return;
- }
-
- if (polygon == null) {
- Log.w(MapboxConstants.TAG, "polygon was null, doing nothing");
- return;
- }
-
- if (polygon.getId() == -1) {
- Log.w(MapboxConstants.TAG, "polygon has an id of -1, indicating the polygon was not added to the map yet.");
- return;
- }
-
- nativeMapView.updatePolygon(polygon);
- }
-
- void updatePolyline(Polyline polyline) {
- if (destroyed) {
- return;
- }
-
- if (polyline == null) {
- Log.w(MapboxConstants.TAG, "polygon was null, doing nothing");
- return;
- }
-
- if (polyline.getId() == -1) {
- Log.w(MapboxConstants.TAG, "polygon has an id of -1, indicating the polygon was not added to the map yet.");
- return;
- }
-
- nativeMapView.updatePolyline(polyline);
- }
-
- private void ensureIconLoaded(Marker marker) {
- Icon icon = marker.getIcon();
- if (icon == null) {
- icon = IconFactory.getInstance(getContext()).defaultMarker();
- marker.setIcon(icon);
- }
- if (!icons.contains(icon)) {
- icons.add(icon);
- loadIcon(icon);
- } else {
- Icon oldIcon = icons.get(icons.indexOf(icon));
- if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
- throw new IconBitmapChangedException();
- }
- }
-
- // this seems to be a costly operation according to the profiler so I'm trying to save some calls
- Marker previousMarker = marker.getId() != -1 ? (Marker) mapboxMap.getAnnotation(marker.getId()) : null;
- if (previousMarker == null || previousMarker.getIcon() == null || previousMarker.getIcon() != marker.getIcon()) {
- marker.setTopOffsetPixels(getTopOffsetPixelsForIcon(icon));
- }
- }
-
- long addMarker(@NonNull Marker marker) {
- if (destroyed) {
- return 0L;
- }
- return nativeMapView.addMarker(marker);
- }
-
- long[] addMarkers(@NonNull List<Marker> markerList) {
- if (destroyed) {
- return new long[]{};
- }
- return nativeMapView.addMarkers(markerList);
- }
-
- long addPolyline(@NonNull Polyline polyline) {
- if (destroyed) {
- return 0L;
- }
- return nativeMapView.addPolyline(polyline);
- }
-
- long[] addPolylines(@NonNull List<Polyline> polylines) {
- if (destroyed) {
- return new long[]{};
- }
- return nativeMapView.addPolylines(polylines);
- }
-
- long addPolygon(@NonNull Polygon polygon) {
- if (destroyed) {
- return 0L;
- }
- return nativeMapView.addPolygon(polygon);
- }
-
- long[] addPolygons(@NonNull List<Polygon> polygons) {
- if (destroyed) {
- return new long[]{};
- }
- return nativeMapView.addPolygons(polygons);
- }
-
- void removeAnnotation(long id) {
- if (destroyed) {
- return;
- }
- nativeMapView.removeAnnotation(id);
- }
-
- void removeAnnotations(@NonNull long[] ids) {
- if (destroyed) {
- return;
- }
- nativeMapView.removeAnnotations(ids);
- }
-
- List<Marker> getMarkersInRect(@NonNull RectF rect) {
- if (destroyed || rect == null) {
- return new ArrayList<>();
- }
-
- long[] ids = nativeMapView.queryPointAnnotations(rect);
-
- List<Long> idsList = new ArrayList<>(ids.length);
- for (int i = 0; i < ids.length; i++) {
- idsList.add(ids[i]);
- }
-
- List<Marker> annotations = new ArrayList<>(ids.length);
- List<Annotation> annotationList = mapboxMap.getAnnotations();
- int count = annotationList.size();
- for (int i = 0; i < count; i++) {
- Annotation annotation = annotationList.get(i);
- if (annotation instanceof Marker && idsList.contains(annotation.getId())) {
- annotations.add((Marker) annotation);
- }
- }
-
- return new ArrayList<>(annotations);
- }
-
- public List<MarkerView> getMarkerViewsInRect(@NonNull RectF rect) {
- if (destroyed || rect == null) {
- return new ArrayList<>();
- }
-
- long[] ids = nativeMapView.queryPointAnnotations(rect);
-
- List<Long> idsList = new ArrayList<>(ids.length);
- for (int i = 0; i < ids.length; i++) {
- idsList.add(ids[i]);
- }
-
- List<MarkerView> annotations = new ArrayList<>(ids.length);
- List<Annotation> annotationList = mapboxMap.getAnnotations();
- int count = annotationList.size();
- for (int i = 0; i < count; i++) {
- Annotation annotation = annotationList.get(i);
- if (annotation instanceof MarkerView) {
- annotations.add((MarkerView) annotation);
- }
- }
-
- return new ArrayList<>(annotations);
- }
-
- /**
- * @return the ViewGroup containing the marker views
- */
- public ViewGroup getMarkerViewContainer() {
- return markerViewContainer;
- }
-
-
- int getTopOffsetPixelsForIcon(Icon icon) {
- if (destroyed) {
- return 0;
+ private NativeMapView nativeMapView;
+ private boolean destroyed;
+ private boolean hasSurface = false;
+
+ private MapboxMap mapboxMap;
+ private MapCallback mapCallback;
+ private boolean onStartCalled;
+ private boolean onStopCalled;
+
+ private MapGestureDetector mapGestureDetector;
+ private MapKeyListener mapKeyListener;
+ private MapZoomButtonController mapZoomButtonController;
+
+ private ConnectivityReceiver connectivityReceiver;
+
+ @UiThread
+ public MapView(@NonNull Context context) {
+ super(context);
+ initialise(context, MapboxMapOptions.createFromAttributes(context, null));
+ }
+
+ @UiThread
+ public MapView(@NonNull Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ initialise(context, MapboxMapOptions.createFromAttributes(context, attrs));
+ }
+
+ @UiThread
+ public MapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ initialise(context, MapboxMapOptions.createFromAttributes(context, attrs));
+ }
+
+ @UiThread
+ public MapView(@NonNull Context context, @Nullable MapboxMapOptions options) {
+ super(context);
+ initialise(context, options);
+ }
+
+ private void initialise(@NonNull final Context context, @NonNull final MapboxMapOptions options) {
+ if (isInEditMode()) {
+ // in IDE, show preview map
+ LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_preview, this);
+ return;
+ }
+
+ // inflate view
+ View view = LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_internal, this);
+ CompassView compassView = (CompassView) view.findViewById(R.id.compassView);
+ MyLocationView myLocationView = (MyLocationView) view.findViewById(R.id.userLocationView);
+ ImageView attrView = (ImageView) view.findViewById(R.id.attributionView);
+ initalizeDrawingSurface(context, options);
+
+ // create native Map object
+ nativeMapView = new NativeMapView(this);
+
+ // callback for focal point invalidation
+ FocalPointInvalidator focalPoint = new FocalPointInvalidator();
+
+ // callback for registering touch listeners
+ RegisterTouchListener registerTouchListener = new RegisterTouchListener();
+
+ // setup components for MapboxMap creation
+ Projection proj = new Projection(nativeMapView);
+ UiSettings uiSettings = new UiSettings(proj, focalPoint, compassView, attrView, view.findViewById(R.id.logoView));
+ TrackingSettings trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPoint);
+ MyLocationViewSettings myLocationViewSettings = new MyLocationViewSettings(myLocationView, proj, focalPoint);
+ MarkerViewManager markerViewManager = new MarkerViewManager((ViewGroup) findViewById(R.id.markerViewContainer));
+ AnnotationManager annotations = new AnnotationManager(nativeMapView, this, markerViewManager);
+ Transform transform = new Transform(nativeMapView, annotations.getMarkerViewManager(), trackingSettings);
+ mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, trackingSettings, myLocationViewSettings, proj,
+ registerTouchListener, annotations);
+
+ // user input
+ mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings, trackingSettings, annotations);
+ mapKeyListener = new MapKeyListener(transform, trackingSettings, uiSettings);
+ mapZoomButtonController = new MapZoomButtonController(this, uiSettings, transform);
+
+ // inject widgets with MapboxMap
+ compassView.setMapboxMap(mapboxMap);
+ myLocationView.setMapboxMap(mapboxMap);
+ attrView.setOnClickListener(new AttributionOnClickListener(context, transform));
+
+ // Ensure this view is interactable
+ setClickable(true);
+ setLongClickable(true);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ requestDisallowInterceptTouchEvent(true);
+
+ // allow onDraw invocation
+ setWillNotDraw(false);
+
+ // notify Map object about current connectivity state
+ nativeMapView.setReachability(isConnected());
+
+ // initialise MapboxMap
+ mapboxMap.initialise(context, options);
+ }
+
+ private void initalizeDrawingSurface(Context context, MapboxMapOptions options) {
+ if (options.getTextureMode()) {
+ TextureView textureView = new TextureView(context);
+ textureView.setSurfaceTextureListener(new SurfaceTextureListener());
+ addView(textureView, 0);
+ } else {
+ SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
+ surfaceView.getHolder().addCallback(new SurfaceCallback());
+ surfaceView.setVisibility(View.VISIBLE);
+ }
+ }
+
+ //
+ // Lifecycle events
+ //
+
+ /**
+ * <p>
+ * You must call this method from the parent's {@link android.app.Activity#onCreate(Bundle)} or
+ * {@link android.app.Fragment#onCreate(Bundle)}.
+ * </p>
+ * You must set a valid access token with {@link Mapbox#getInstance(Context, String)}) before you call this method
+ * or an exception will be thrown.
+ *
+ * @param savedInstanceState Pass in the parent's savedInstanceState.
+ * @see Mapbox#getInstance(Context, String)
+ */
+ @UiThread
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ nativeMapView.setAccessToken(Mapbox.getAccessToken());
+
+ if (savedInstanceState == null) {
+ MapboxEvent.trackMapLoadEvent();
+ } else if (savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) {
+ mapboxMap.onRestoreInstanceState(savedInstanceState);
+ }
+
+ // Initialize EGL
+ nativeMapView.initializeDisplay();
+ nativeMapView.initializeContext();
+
+ addOnMapChangedListener(mapCallback = new MapCallback(mapboxMap));
+ }
+
+ /**
+ * You must call this method from the parent's {@link android.app.Activity#onSaveInstanceState(Bundle)}
+ * or {@link android.app.Fragment#onSaveInstanceState(Bundle)}.
+ *
+ * @param outState Pass in the parent's outState.
+ */
+
+ @UiThread
+ public void onSaveInstanceState(@NonNull Bundle outState) {
+ outState.putBoolean(MapboxConstants.STATE_HAS_SAVED_STATE, true);
+ mapboxMap.onSaveInstanceState(outState);
+ }
+
+ /**
+ * You must call this method from the parent's {@link Activity#onStart()} or {@link Fragment#onStart()}
+ */
+ @UiThread
+ public void onStart() {
+ onStartCalled = true;
+ mapboxMap.onStart();
+ registerConnectivityReceiver();
+ }
+
+ /**
+ * You must call this method from the parent's {@link Activity#onResume()} or {@link Fragment#onResume()}.
+ */
+ @UiThread
+ public void onResume() {
+ if (!onStartCalled) {
+ // TODO: 26/10/16, can be removed after 5.0.0 release
+ throw new IllegalStateException("MapView#onStart() was not called. "
+ + "You must call this method from the parent's {@link Activity#onStart()} or {@link Fragment#onStart()}.");
+ }
+ }
+
+ /**
+ * You must call this method from the parent's {@link Activity#onPause()} or {@link Fragment#onPause()}.
+ */
+ @UiThread
+ public void onPause() {
+ // replaced by onStop in v5.0.0, keep around for future development
+ }
+
+ /**
+ * You must call this method from the parent's {@link Activity#onStop()} or {@link Fragment#onStop()}.
+ */
+ @UiThread
+ public void onStop() {
+ onStopCalled = true;
+ mapboxMap.onStop();
+ unregisterConnectivityReceiver();
+ }
+
+ /**
+ * You must call this method from the parent's {@link Activity#onDestroy()} or {@link Fragment#onDestroy()}.
+ */
+ @UiThread
+ public void onDestroy() {
+ if (!onStopCalled) {
+ // TODO: 26/10/16, can be removed after 5.0.0 release
+ throw new IllegalStateException("MapView#onStop() was not called. "
+ + "You must call this method from the parent's {@link Activity#onStop()} or {@link Fragment#onStop()}.");
+ }
+
+ destroyed = true;
+ nativeMapView.terminateContext();
+ nativeMapView.terminateDisplay();
+ nativeMapView.destroySurface();
+ nativeMapView.destroy();
+ nativeMapView = null;
+ }
+
+ private void registerConnectivityReceiver() {
+ getContext().registerReceiver(connectivityReceiver = new ConnectivityReceiver(),
+ new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
+ }
+
+ private void unregisterConnectivityReceiver() {
+ if (connectivityReceiver != null) {
+ getContext().unregisterReceiver(connectivityReceiver);
+ connectivityReceiver = null;
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ mapZoomButtonController.setVisible(true);
+ }
+ return mapGestureDetector.onTouchEvent(event) || super.onTouchEvent(event);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return mapKeyListener.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+ return mapKeyListener.onKeyLongPress(keyCode, event) || super.onKeyLongPress(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return mapKeyListener.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ return mapKeyListener.onTrackballEvent(event) || super.onTrackballEvent(event);
+ }
+
+ @Override
+ public boolean onGenericMotionEvent(MotionEvent event) {
+ return mapGestureDetector.onGenericMotionEvent(event) || super.onGenericMotionEvent(event);
+ }
+
+ @Override
+ public boolean onHoverEvent(MotionEvent event) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ case MotionEvent.ACTION_HOVER_MOVE:
+ mapZoomButtonController.setVisible(true);
+ return true;
+
+ case MotionEvent.ACTION_HOVER_EXIT:
+ mapZoomButtonController.setVisible(false);
+ return true;
+
+ default:
+ // We are not interested in this event
+ return false;
+ }
+ }
+
+ /**
+ * You must call this method from the parent's {@link Activity#onLowMemory()} or {@link Fragment#onLowMemory()}.
+ */
+ @UiThread
+ public void onLowMemory() {
+ nativeMapView.onLowMemory();
+ }
+
+ // Called when debug mode is enabled to update a FPS counter
+ // Called via JNI from NativeMapView
+ // Forward to any listener
+ protected void onFpsChanged(final double fps) {
+ final MapboxMap.OnFpsChangedListener listener = mapboxMap.getOnFpsChangedListener();
+ if (listener != null) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ listener.onFpsChanged(fps);
}
-
- return (int) (nativeMapView.getTopOffsetPixelsForAnnotationSymbol(icon.getId())
- * screenDensity);
+ });
}
+ }
- void setContentPadding(int left, int top, int right, int bottom) {
- if (destroyed) {
- return;
- }
-
-// if (left == contentPaddingLeft && top == contentPaddingTop && right == contentPaddingRight && bottom == contentPaddingBottom) {
-// return;
-// }
-
- contentPaddingLeft = left;
- contentPaddingTop = top;
- contentPaddingRight = right;
- contentPaddingBottom = bottom;
-
- int[] userLocationViewPadding = mapboxMap.getMyLocationViewSettings().getPadding();
- left += userLocationViewPadding[0];
- top += userLocationViewPadding[1];
- right += userLocationViewPadding[2];
- bottom += userLocationViewPadding[3];
-
- nativeMapView.setContentPadding(top / screenDensity, left / screenDensity, bottom / screenDensity, right / screenDensity);
+ /**
+ * <p>
+ * Loads a new map style from the specified URL.
+ * </p>
+ * {@code url} can take the following forms:
+ * <ul>
+ * <li>{@code Style.*}: load one of the bundled styles in {@link Style}.</li>
+ * <li>{@code mapbox://styles/<user>/<style>}:
+ * retrieves the style from a <a href="https://www.mapbox.com/account/">Mapbox account.</a>
+ * {@code user} is your username. {@code style} is the ID of your custom
+ * style created in <a href="https://www.mapbox.com/studio">Mapbox Studio</a>.</li>
+ * <li>{@code http://...} or {@code https://...}:
+ * retrieves the style over the Internet from any web server.</li>
+ * <li>{@code asset://...}:
+ * reads the style from the APK {@code assets/} directory.
+ * This is used to load a style bundled with your app.</li>
+ * <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li>
+ * </ul>
+ * <p>
+ * This method is asynchronous and will return immediately before the style finishes loading.
+ * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event.
+ * </p>
+ * If the style fails to load or an invalid style URL is set, the map view will become blank.
+ * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be sent.
+ *
+ * @param url The URL of the map style
+ * @see Style
+ */
+ public void setStyleUrl(@NonNull String url) {
+ if (destroyed) {
+ return;
}
- public void invalidateContentPadding() {
- setContentPadding(contentPaddingLeft, contentPaddingTop, contentPaddingRight, contentPaddingBottom);
-
- if (!mapboxMap.getTrackingSettings().isLocationTrackingDisabled()) {
- setFocalPoint(new PointF(myLocationView.getCenterX(), myLocationView.getCenterY()));
- } else {
- setFocalPoint(null);
- }
+ // stopgap for https://github.com/mapbox/mapbox-gl-native/issues/6242
+ if (TextUtils.isEmpty(nativeMapView.getAccessToken())) {
+ nativeMapView.setAccessToken(Mapbox.getAccessToken());
}
- double getMetersPerPixelAtLatitude(@FloatRange(from = -180, to = 180) double latitude) {
- if (destroyed) {
- return 0;
- }
+ nativeMapView.setStyleUrl(url);
+ }
- return nativeMapView.getMetersPerPixelAtLatitude(latitude, getZoom()) / screenDensity;
- }
+ //
+ // Rendering
+ //
- //
- // Mapbox Core GL Camera
- //
+ // Called when the map needs to be rerendered
+ // Called via JNI from NativeMapView
+ protected void onInvalidate() {
+ postInvalidate();
+ }
- void jumpTo(double bearing, LatLng center, double pitch, double zoom) {
- if (destroyed) {
- return;
- }
- nativeMapView.cancelTransitions();
- nativeMapView.jumpTo(bearing, center, pitch, zoom);
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if (isInEditMode()) {
+ return;
}
- void easeTo(double bearing, LatLng center, long duration, double pitch, double zoom, boolean easingInterpolator, @Nullable final MapboxMap.CancelableCallback cancelableCallback) {
- if (destroyed) {
- return;
- }
- nativeMapView.cancelTransitions();
-
- // Register callbacks early enough
- if (cancelableCallback != null) {
- addOnMapChangedListener(new OnMapChangedListener() {
- @Override
- public void onMapChanged(@MapChange int change) {
- if (change == REGION_DID_CHANGE_ANIMATED) {
- cancelableCallback.onFinish();
-
- // Clean up after self
- removeOnMapChangedListener(this);
- }
- }
- });
- }
-
- nativeMapView.easeTo(bearing, center, duration, pitch, zoom, easingInterpolator);
+ if (destroyed) {
+ return;
}
- void flyTo(double bearing, LatLng center, long duration, double pitch, double zoom, @Nullable final MapboxMap.CancelableCallback cancelableCallback) {
- if (destroyed) {
- return;
- }
- nativeMapView.cancelTransitions();
-
- // Register callbacks early enough
- if (cancelableCallback != null) {
- addOnMapChangedListener(new OnMapChangedListener() {
- @Override
- public void onMapChanged(@MapChange int change) {
- if (change == REGION_DID_CHANGE_ANIMATED) {
- cancelableCallback.onFinish();
-
- // Clean up after self
- removeOnMapChangedListener(this);
- }
- }
- });
- }
-
- nativeMapView.flyTo(bearing, center, duration, pitch, zoom);
+ if (!hasSurface) {
+ return;
}
- private void adjustTopOffsetPixels() {
- List<Annotation> annotations = mapboxMap.getAnnotations();
- int count = annotations.size();
- for (int i = 0; i < count; i++) {
- Annotation annotation = annotations.get(i);
- if (annotation instanceof Marker) {
- Marker marker = (Marker) annotation;
- marker.setTopOffsetPixels(
- getTopOffsetPixelsForIcon(marker.getIcon()));
- }
- }
+ nativeMapView.render();
+ }
- for (Marker marker : mapboxMap.getSelectedMarkers()) {
- if (marker.isInfoWindowShown()) {
- marker.hideInfoWindow();
- marker.showInfoWindow(mapboxMap, this);
- }
- }
+ @Override
+ protected void onSizeChanged(int width, int height, int oldw, int oldh) {
+ if (destroyed) {
+ return;
}
- private void reloadMarkers() {
- if (destroyed) {
- return;
- }
- List<Annotation> annotations = mapboxMap.getAnnotations();
- 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);
- }
- }
+ if (!isInEditMode()) {
+ nativeMapView.resizeView(width, height);
}
+ }
- //
- // Rendering
- //
+ private class SurfaceCallback implements SurfaceHolder.Callback {
- // Called when the map needs to be rerendered
- // Called via JNI from NativeMapView
- protected void onInvalidate() {
- postInvalidate();
- }
+ private Surface surface;
@Override
- public void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (isInEditMode()) {
- return;
- }
-
- if (destroyed) {
- return;
- }
-
- if (!hasSurface) {
- return;
- }
-
- nativeMapView.render();
+ public void surfaceCreated(SurfaceHolder holder) {
+ nativeMapView.createSurface(surface = holder.getSurface());
+ hasSurface = true;
}
@Override
- protected void onSizeChanged(int width, int height, int oldw, int oldh) {
- if (destroyed) {
- return;
- }
-
- if (!isInEditMode()) {
- nativeMapView.resizeView((int) (width / screenDensity), (int) (height / screenDensity));
- }
- }
-
- double getScale() {
- if (destroyed) {
- return 0;
- }
-
- return nativeMapView.getScale();
- }
-
- private class SurfaceCallback implements SurfaceHolder.Callback {
-
- private Surface surface;
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- nativeMapView.createSurface(surface = holder.getSurface());
- hasSurface = true;
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- if (destroyed) {
- return;
- }
- nativeMapView.resizeFramebuffer(width, height);
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- hasSurface = false;
-
- if (nativeMapView != null) {
- nativeMapView.destroySurface();
- }
- surface.release();
- }
- }
-
- // This class handles TextureView callbacks
- private class SurfaceTextureListener implements TextureView.SurfaceTextureListener {
-
- private Surface surface;
-
- // Called when the native surface texture has been created
- // Must do all EGL/GL ES initialization here
- @Override
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- nativeMapView.createSurface(this.surface = new Surface(surface));
- nativeMapView.resizeFramebuffer(width, height);
- hasSurface = true;
- }
-
- // Called when the native surface texture has been destroyed
- // Must do all EGL/GL ES destruction here
- @Override
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- hasSurface = false;
-
- if (nativeMapView != null) {
- nativeMapView.destroySurface();
- }
- this.surface.release();
- return true;
- }
-
- // Called when the format or size of the native surface texture has been changed
- // Must handle window resizing here.
- @Override
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
- if (destroyed) {
- return;
- }
-
- nativeMapView.resizeFramebuffer(width, height);
- }
-
- // Called when the SurfaceTexure frame is drawn to screen
- // Must sync with UI here
- @Override
- public void onSurfaceTextureUpdated(SurfaceTexture surface) {
- if (destroyed) {
- return;
- }
- compassView.update(getDirection());
- myLocationView.update();
- mapboxMap.getMarkerViewManager().update();
-
- for (InfoWindow infoWindow : mapboxMap.getInfoWindows()) {
- infoWindow.update();
- }
- }
- }
-
- CameraPosition invalidateCameraPosition() {
- if (destroyed) {
- return new CameraPosition.Builder().build();
- }
- CameraPosition position = new CameraPosition.Builder(nativeMapView.getCameraValues()).build();
- myLocationView.setCameraPosition(position);
- mapboxMap.getMarkerViewManager().setTilt((float) position.tilt);
- return position;
- }
-
- double getBearing() {
- if (destroyed) {
- return 0;
- }
-
- double direction = -nativeMapView.getBearing();
-
- while (direction > 360) {
- direction -= 360;
- }
- while (direction < 0) {
- direction += 360;
- }
-
- return direction;
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ if (destroyed) {
+ return;
+ }
+ nativeMapView.resizeFramebuffer(width, height);
}
- void setBearing(float bearing) {
- if (destroyed) {
- return;
- }
- myLocationView.setBearing(bearing);
- nativeMapView.setBearing(bearing);
- }
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ hasSurface = false;
- void setBearing(float bearing, long duration) {
- if (destroyed) {
- return;
- }
- myLocationView.setBearing(bearing);
- nativeMapView.setBearing(bearing, duration);
+ if (nativeMapView != null) {
+ nativeMapView.destroySurface();
+ }
+ surface.release();
}
+ }
- void setBearing(double bearing, float focalX, float focalY) {
- if (destroyed) {
- return;
- }
- myLocationView.setBearing(bearing);
- nativeMapView.setBearing(bearing, focalX, focalY);
- }
+ // This class handles TextureView callbacks
+ private class SurfaceTextureListener implements TextureView.SurfaceTextureListener {
- //
- // View events
- //
+ private Surface surface;
- // Called when view is no longer connected
+ // Called when the native surface texture has been created
+ // Must do all EGL/GL ES initialization here
@Override
- @CallSuper
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- // Required by ZoomButtonController (from Android SDK documentation)
- if (mapboxMap.getUiSettings().isZoomControlsEnabled()) {
- zoomButtonsController.setVisible(false);
- }
-
- // make sure we don't leak location listener
- if (myLocationListener != null) {
- // cleanup to prevent memory leak
- LocationServices services = LocationServices.getLocationServices(getContext());
- services.removeLocationListener(myLocationListener);
- myLocationListener = null;
- }
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+ nativeMapView.createSurface(this.surface = new Surface(surface));
+ nativeMapView.resizeFramebuffer(width, height);
+ hasSurface = true;
}
- // Called when view is hidden and shown
+ // Called when the native surface texture has been destroyed
+ // Must do all EGL/GL ES destruction here
@Override
- protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
- if (isInEditMode()) {
- return;
- }
-
- // Required by ZoomButtonController (from Android SDK documentation)
- if (visibility == View.VISIBLE) {
- if (mapboxMap != null && mapboxMap.getUiSettings().isZoomControlsEnabled()) {
- zoomButtonsController.setVisible(true);
- }
- } else {
- if (mapboxMap != null && mapboxMap.getUiSettings().isZoomControlsEnabled()) {
- zoomButtonsController.setVisible(false);
- }
- }
- }
-
- //
- // Touch events
- //
-
- /**
- * Helper method for tracking gesture events
- *
- * @param gestureId Type of Gesture See {@see MapboxEvent#GESTURE_SINGLETAP MapboxEvent#GESTURE_DOUBLETAP MapboxEvent#GESTURE_TWO_FINGER_SINGLETAP MapboxEvent#GESTURE_QUICK_ZOOM MapboxEvent#GESTURE_PAN_START MapboxEvent#GESTURE_PINCH_START MapboxEvent#GESTURE_ROTATION_START MapboxEvent#GESTURE_PITCH_START}
- * @param xCoordinate Original x screen coordinate at start of gesture
- * @param yCoordinate Original y screen cooridnate at start of gesture
- */
- private void trackGestureEvent(@NonNull String gestureId, @NonNull float xCoordinate, @NonNull float yCoordinate) {
- LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate));
-
- // NaN and Infinite checks to prevent JSON errors at send to server time
- if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) {
- Log.d(MapView.class.getSimpleName(), "trackGestureEvent() has a NaN lat or lon. Returning.");
- return;
- }
-
- if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) {
- Log.d(MapView.class.getSimpleName(), "trackGestureEvent() has an Infinite lat or lon. Returning.");
- return;
- }
-
- Hashtable<String, Object> evt = new Hashtable<>();
- evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_CLICK);
- evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate());
- evt.put(MapboxEvent.KEY_GESTURE_ID, gestureId);
- evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude());
- evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude());
- evt.put(MapboxEvent.KEY_ZOOM, mapboxMap.getCameraPosition().zoom);
-
- MapboxEventManager.getMapboxEventManager().pushEvent(evt);
- }
-
- /**
- * Helper method for tracking DragEnd gesture event
- * See {@see MapboxEvent#TYPE_MAP_DRAGEND}
- *
- * @param xCoordinate Original x screen coordinate at end of drag
- * @param yCoordinate Orginal y screen coordinate at end of drag
- */
- private void trackGestureDragEndEvent(@NonNull float xCoordinate, @NonNull float yCoordinate) {
- LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate));
-
- // NaN and Infinite checks to prevent JSON errors at send to server time
- if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) {
- Log.d(MapView.class.getSimpleName(), "trackGestureDragEndEvent() has a NaN lat or lon. Returning.");
- return;
- }
-
- if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) {
- Log.d(MapView.class.getSimpleName(), "trackGestureDragEndEvent() has an Infinite lat or lon. Returning.");
- return;
- }
-
- Hashtable<String, Object> evt = new Hashtable<>();
- evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_DRAGEND);
- evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate());
- evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude());
- evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude());
- evt.put(MapboxEvent.KEY_ZOOM, mapboxMap.getCameraPosition().zoom);
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+ hasSurface = false;
- MapboxEventManager.getMapboxEventManager().pushEvent(evt);
+ if (nativeMapView != null) {
+ nativeMapView.destroySurface();
+ }
+ this.surface.release();
+ return true;
}
- // Called when user touches the screen, all positions are absolute
+ // Called when the format or size of the native surface texture has been changed
+ // Must handle window resizing here.
@Override
- public boolean onTouchEvent(@NonNull MotionEvent event) {
- // Check and ignore non touch or left clicks
- if (destroyed) {
- return super.onTouchEvent(event);
- }
-
- if ((event.getButtonState() != 0) && (event.getButtonState() != MotionEvent.BUTTON_PRIMARY)) {
- return false;
- }
-
- // Check two finger gestures first
- rotateGestureDetector.onTouchEvent(event);
- scaleGestureDetector.onTouchEvent(event);
- shoveGestureDetector.onTouchEvent(event);
-
- // Handle two finger tap
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- // First pointer down
- nativeMapView.setGestureInProgress(true);
- break;
-
- case MotionEvent.ACTION_POINTER_DOWN:
- // Second pointer down
- twoTap = event.getPointerCount() == 2
- && mapboxMap.getUiSettings().isZoomGesturesEnabled();
- if (twoTap) {
- // Confirmed 2nd Finger Down
- trackGestureEvent(MapboxEvent.GESTURE_TWO_FINGER_SINGLETAP, event.getX(), event.getY());
- }
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- // Second pointer up
- break;
-
- case MotionEvent.ACTION_UP:
- // First pointer up
- long tapInterval = event.getEventTime() - event.getDownTime();
- boolean isTap = tapInterval <= ViewConfiguration.getTapTimeout();
- boolean inProgress = rotateGestureDetector.isInProgress()
- || scaleGestureDetector.isInProgress()
- || shoveGestureDetector.isInProgress();
-
- if (twoTap && isTap && !inProgress) {
- if (focalPoint != null) {
- zoom(false, focalPoint.x, focalPoint.y);
- } else {
- PointF focalPoint = TwoFingerGestureDetector.determineFocalPoint(event);
- zoom(false, focalPoint.x, focalPoint.y);
- }
- twoTap = false;
- return true;
- }
-
- // Scroll / Pan Has Stopped
- if (scrollInProgress) {
- trackGestureDragEndEvent(event.getX(), event.getY());
- scrollInProgress = false;
- }
-
- twoTap = false;
- nativeMapView.setGestureInProgress(false);
- break;
-
- case MotionEvent.ACTION_CANCEL:
- twoTap = false;
- nativeMapView.setGestureInProgress(false);
- break;
- }
-
- boolean retVal = gestureDetector.onTouchEvent(event);
- return retVal || super.onTouchEvent(event);
- }
-
- // This class handles one finger gestures
- private class GestureListener extends GestureDetector.SimpleOnGestureListener {
-
- // Must always return true otherwise all events are ignored
- @Override
- @SuppressLint("ResourceType")
- public boolean onDown(MotionEvent event) {
- // Show the zoom controls
- if (mapboxMap.getUiSettings().isZoomControlsEnabled()) {
- zoomButtonsController.setVisible(true);
- }
- return true;
- }
-
- // Called for double taps
- @Override
- public boolean onDoubleTapEvent(MotionEvent e) {
- if (destroyed || !mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return false;
- }
-
- switch (e.getAction()) {
- case MotionEvent.ACTION_DOWN:
- break;
- case MotionEvent.ACTION_MOVE:
- break;
- case MotionEvent.ACTION_UP:
- if (quickZoom) {
- // insert here?
- quickZoom = false;
- break;
- }
-
- // Single finger double tap
- if (focalPoint != null) {
- // User provided focal point
- zoom(true, focalPoint.x, focalPoint.y);
- } else {
- // Zoom in on gesture
- zoom(true, e.getX(), e.getY());
- }
- break;
- }
-
- trackGestureEvent(MapboxEvent.GESTURE_DOUBLETAP, e.getX(), e.getY());
-
- return true;
- }
-
- @Override
- public boolean onSingleTapUp(MotionEvent motionEvent) {
- if (destroyed) {
- return false;
- }
- // Cancel any animation
- nativeMapView.cancelTransitions();
- return true;
- }
-
- @Override
- public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
- List<Marker> selectedMarkers = mapboxMap.getSelectedMarkers();
-
- PointF tapPoint = new PointF(motionEvent.getX(), motionEvent.getY());
- float toleranceSides = 4 * screenDensity;
- float toleranceTopBottom = 10 * screenDensity;
-
- RectF tapRect = new RectF((tapPoint.x - averageIconWidth / 2 - toleranceSides) / screenDensity,
- (tapPoint.y - averageIconHeight / 2 - toleranceTopBottom) / screenDensity,
- (tapPoint.x + averageIconWidth / 2 + toleranceSides) / screenDensity,
- (tapPoint.y + averageIconHeight / 2 + toleranceTopBottom) / screenDensity);
-
- List<Marker> nearbyMarkers = getMarkersInRect(tapRect);
- long newSelectedMarkerId = -1;
-
- if (nearbyMarkers != null && nearbyMarkers.size() > 0) {
- Collections.sort(nearbyMarkers);
- for (Marker nearbyMarker : nearbyMarkers) {
- boolean found = false;
- for (Marker selectedMarker : selectedMarkers) {
- if (selectedMarker.equals(nearbyMarker)) {
- found = true;
- }
- }
- if (!found) {
- newSelectedMarkerId = nearbyMarker.getId();
- break;
- }
- }
- }
-
- if (newSelectedMarkerId >= 0) {
- List<Annotation> annotations = mapboxMap.getAnnotations();
- int count = annotations.size();
- for (int i = 0; i < count; i++) {
- Annotation annotation = annotations.get(i);
- if (annotation instanceof Marker) {
- if (annotation.getId() == newSelectedMarkerId) {
- if (selectedMarkers.isEmpty() || !selectedMarkers.contains(annotation)) {
- if (!(annotation instanceof MarkerView)) {
- mapboxMap.selectMarker((Marker) annotation);
- } else {
- mapboxMap.getMarkerViewManager().onClickMarkerView((MarkerView) annotation);
- }
- }
- break;
- }
- }
- }
- } else {
- if (mapboxMap.getUiSettings().isDeselectMarkersOnTap()) {
- // deselect any selected marker
- mapboxMap.deselectMarkers();
- }
-
- // notify app of map click
- MapboxMap.OnMapClickListener listener = mapboxMap.getOnMapClickListener();
- if (listener != null) {
- LatLng point = projection.fromScreenLocation(tapPoint);
- listener.onMapClick(point);
- }
- }
-
- trackGestureEvent(MapboxEvent.GESTURE_SINGLETAP, motionEvent.getX(), motionEvent.getY());
- return true;
- }
-
- // Called for a long press
- @Override
- public void onLongPress(MotionEvent motionEvent) {
- MapboxMap.OnMapLongClickListener listener = mapboxMap.getOnMapLongClickListener();
- if (listener != null && !quickZoom) {
- LatLng point = projection.fromScreenLocation(new PointF(motionEvent.getX(), motionEvent.getY()));
- listener.onMapLongClick(point);
- }
- }
-
- // Called for flings
- @Override
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- if (destroyed || !mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- resetTrackingModesIfRequired(true, false);
-
- // Fling the map
- float ease = 0.25f;
-
- velocityX = velocityX * ease;
- velocityY = velocityY * ease;
-
- double speed = Math.sqrt(velocityX * velocityX + velocityY * velocityY);
- double deceleration = 2500;
- double duration = speed / (deceleration * ease);
-
- // Cancel any animation
- nativeMapView.cancelTransitions();
-
- nativeMapView.moveBy(velocityX * duration / 2.0 / screenDensity, velocityY * duration / 2.0 / screenDensity, (long) (duration * 1000.0f));
-
- MapboxMap.OnFlingListener listener = mapboxMap.getOnFlingListener();
- if (listener != null) {
- listener.onFling();
- }
-
- trackGestureEvent(MapboxEvent.GESTURE_PAN_START, e1.getX(), e1.getY());
- return true;
- }
-
- // Called for drags
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- if (!scrollInProgress) {
- scrollInProgress = true;
- }
- if (destroyed || !mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- if (dragStarted) {
- return false;
- }
-
- requestDisallowInterceptTouchEvent(true);
-
- // reset tracking if needed
- resetTrackingModesIfRequired(true, false);
- // Cancel any animation
- nativeMapView.cancelTransitions();
-
- // Scroll the map
- nativeMapView.moveBy(-distanceX / screenDensity, -distanceY / screenDensity);
-
- MapboxMap.OnScrollListener listener = mapboxMap.getOnScrollListener();
- if (listener != null) {
- listener.onScroll();
- }
- return true;
- }
- }
-
- // This class handles two finger gestures and double-tap drag gestures
- private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
-
- long beginTime = 0;
- float scaleFactor = 1.0f;
-
- // Called when two fingers first touch the screen
- @Override
- public boolean onScaleBegin(ScaleGestureDetector detector) {
- if (destroyed || !mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return false;
- }
-
- beginTime = detector.getEventTime();
- trackGestureEvent(MapboxEvent.GESTURE_PINCH_START, detector.getFocusX(), detector.getFocusY());
- return true;
- }
-
- // Called when fingers leave screen
- @Override
- public void onScaleEnd(ScaleGestureDetector detector) {
- beginTime = 0;
- scaleFactor = 1.0f;
- zoomStarted = false;
- }
-
- // Called each time a finger moves
- // Called for pinch zooms and quickzooms/quickscales
- @Override
- public boolean onScale(ScaleGestureDetector detector) {
- UiSettings uiSettings = mapboxMap.getUiSettings();
- if (destroyed || !uiSettings.isZoomGesturesEnabled()) {
- return super.onScale(detector);
- }
-
- // If scale is large enough ignore a tap
- scaleFactor *= detector.getScaleFactor();
- if ((scaleFactor > 1.05f) || (scaleFactor < 0.95f)) {
- zoomStarted = true;
- }
-
- // Ignore short touches in case it is a tap
- // Also ignore small scales
- long time = detector.getEventTime();
- long interval = time - beginTime;
- if (!zoomStarted && (interval <= ViewConfiguration.getTapTimeout())) {
- return false;
- }
-
- if (!zoomStarted) {
- return false;
- }
-
- if (dragStarted) {
- return false;
- }
-
- // Cancel any animation
- nativeMapView.cancelTransitions();
-
- // Gesture is a quickzoom if there aren't two fingers
- quickZoom = !twoTap;
-
- // make an assumption here; if the zoom center is specified by the gesture, it's NOT going
- // to be in the center of the map. Therefore the zoom will translate the map center, so tracking
- // should be disabled.
-
- resetTrackingModesIfRequired(!quickZoom, false);
- // Scale the map
- if (focalPoint != null) {
- // arround user provided focal point
- nativeMapView.scaleBy(detector.getScaleFactor(), focalPoint.x / screenDensity, focalPoint.y / screenDensity);
- } else if (quickZoom) {
- // around center map
- nativeMapView.scaleBy(detector.getScaleFactor(), (getWidth() / 2) / screenDensity, (getHeight() / 2) / screenDensity);
- } else {
- // around gesture
- nativeMapView.scaleBy(detector.getScaleFactor(), detector.getFocusX() / screenDensity, detector.getFocusY() / screenDensity);
- }
-
- return true;
- }
- }
-
- // This class handles two finger rotate gestures
- private class RotateGestureListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
-
- long beginTime = 0;
- float totalAngle = 0.0f;
- boolean started = false;
-
- // Called when two fingers first touch the screen
- @Override
- public boolean onRotateBegin(RotateGestureDetector detector) {
- if (destroyed || !mapboxMap.getTrackingSettings().isRotateGestureCurrentlyEnabled()) {
- return false;
- }
-
- beginTime = detector.getEventTime();
- trackGestureEvent(MapboxEvent.GESTURE_ROTATION_START, detector.getFocusX(), detector.getFocusY());
- return true;
- }
-
- // Called when the fingers leave the screen
- @Override
- public void onRotateEnd(RotateGestureDetector detector) {
- beginTime = 0;
- totalAngle = 0.0f;
- started = false;
- }
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+ if (destroyed) {
+ return;
+ }
- // Called each time one of the two fingers moves
- // Called for rotation
- @Override
- public boolean onRotate(RotateGestureDetector detector) {
- if (destroyed || !mapboxMap.getTrackingSettings().isRotateGestureCurrentlyEnabled() || dragStarted) {
- return false;
- }
-
- // If rotate is large enough ignore a tap
- // Also is zoom already started, don't rotate
- totalAngle += detector.getRotationDegreesDelta();
- if (!zoomStarted && ((totalAngle > 20.0f) || (totalAngle < -20.0f))) {
- started = true;
- }
-
- // Ignore short touches in case it is a tap
- // Also ignore small rotate
- long time = detector.getEventTime();
- long interval = time - beginTime;
- if (!started && (interval <= ViewConfiguration.getTapTimeout())) {
- return false;
- }
-
- if (!started) {
- return false;
- }
-
- // Cancel any animation
- nativeMapView.cancelTransitions();
-
- // rotation constitutes translation of anything except the center of
- // rotation, so cancel both location and bearing tracking if required
-
- resetTrackingModesIfRequired(true, true);
-
- // Get rotate value
- double bearing = nativeMapView.getBearing();
- bearing += detector.getRotationDegreesDelta();
-
- // Rotate the map
- if (focalPoint != null) {
- // User provided focal point
- setBearing(bearing, focalPoint.x / screenDensity, focalPoint.y / screenDensity);
- } else {
- // around gesture
- setBearing(bearing, detector.getFocusX() / screenDensity, detector.getFocusY() / screenDensity);
- }
- return true;
- }
+ nativeMapView.resizeFramebuffer(width, height);
}
- // This class handles a vertical two-finger shove. (If you place two fingers on screen with
- // less than a 20 degree angle between them, this will detect movement on the Y-axis.)
- private class ShoveGestureListener implements ShoveGestureDetector.OnShoveGestureListener {
-
- long beginTime = 0;
- float totalDelta = 0.0f;
- boolean started = false;
-
- @Override
- public boolean onShoveBegin(ShoveGestureDetector detector) {
- if (!mapboxMap.getUiSettings().isTiltGesturesEnabled()) {
- return false;
- }
-
- beginTime = detector.getEventTime();
- trackGestureEvent(MapboxEvent.GESTURE_PITCH_START, detector.getFocusX(), detector.getFocusY());
- return true;
- }
-
- @Override
- public void onShoveEnd(ShoveGestureDetector detector) {
- beginTime = 0;
- totalDelta = 0.0f;
- started = false;
- dragStarted = false;
- }
-
- @Override
- public boolean onShove(ShoveGestureDetector detector) {
- if (destroyed || !mapboxMap.getUiSettings().isTiltGesturesEnabled()) {
- return false;
- }
-
- // If tilt is large enough ignore a tap
- // Also if zoom already started, don't tilt
- totalDelta += detector.getShovePixelsDelta();
- if (!zoomStarted && ((totalDelta > 10.0f) || (totalDelta < -10.0f))) {
- started = true;
- }
-
- // Ignore short touches in case it is a tap
- // Also ignore small tilt
- long time = detector.getEventTime();
- long interval = time - beginTime;
- if (!started && (interval <= ViewConfiguration.getTapTimeout())) {
- return false;
- }
-
- if (!started) {
- return false;
- }
-
- // Cancel any animation
- nativeMapView.cancelTransitions();
-
- // Get tilt value (scale and clamp)
- double pitch = getTilt();
- pitch -= 0.1 * detector.getShovePixelsDelta();
- pitch = Math.max(MapboxConstants.MINIMUM_TILT, Math.min(MapboxConstants.MAXIMUM_TILT, pitch));
-
- // Tilt the map
- mapboxMap.setTilt(pitch);
-
- dragStarted = true;
-
- return true;
- }
- }
-
- // This class handles input events from the zoom control buttons
- // Zoom controls allow single touch only devices to zoom in and out
- private class OnZoomListener implements ZoomButtonsController.OnZoomListener {
-
- // Not used
- @Override
- public void onVisibilityChanged(boolean visible) {
- // Ignore
- }
-
- // Called when user pushes a zoom button
- @Override
- public void onZoom(boolean zoomIn) {
- if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return;
- }
- zoom(zoomIn);
- }
- }
-
- //
- // Input events
- //
-
- // Called when the user presses a key, also called for repeating keys held
- // down
+ // Called when the SurfaceTexure frame is drawn to screen
+ // Must sync with UI here
@Override
- public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
- if (destroyed) {
- return super.onKeyDown(keyCode, event);
- }
-
- // If the user has held the scroll key down for a while then accelerate
- // the scroll speed
- double scrollDist = event.getRepeatCount() >= 5 ? 50.0 : 10.0;
-
- // Check which key was pressed via hardware/real key code
- switch (keyCode) {
- // Tell the system to track these keys for long presses on
- // onKeyLongPress is fired
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- event.startTracking();
- return true;
-
- case KeyEvent.KEYCODE_DPAD_LEFT:
- if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- // Cancel any animation
- nativeMapView.cancelTransitions();
-
- // Move left
- nativeMapView.moveBy(scrollDist / screenDensity, 0.0 / screenDensity);
- return true;
-
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- // Cancel any animation
- nativeMapView.cancelTransitions();
-
- // Move right
- nativeMapView.moveBy(-scrollDist / screenDensity, 0.0 / screenDensity);
- return true;
-
- case KeyEvent.KEYCODE_DPAD_UP:
- if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- // Cancel any animation
- nativeMapView.cancelTransitions();
-
- // Move up
- nativeMapView.moveBy(0.0 / screenDensity, scrollDist / screenDensity);
- return true;
-
- case KeyEvent.KEYCODE_DPAD_DOWN:
- if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- // Cancel any animation
- nativeMapView.cancelTransitions();
-
- // Move down
- nativeMapView.moveBy(0.0 / screenDensity, -scrollDist / screenDensity);
- return true;
-
- default:
- // We are not interested in this key
- return super.onKeyUp(keyCode, event);
- }
- }
-
- // Called when the user long presses a key that is being tracked
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ if (destroyed) {
+ return;
+ }
+ mapboxMap.onUpdate();
+ }
+ }
+
+ //
+ // View events
+ //
+
+ // Called when view is no longer connected
+ @Override
+ @CallSuper
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mapZoomButtonController.setVisible(false);
+ }
+
+ // Called when view is hidden and shown
+ @Override
+ protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
+ if (isInEditMode()) {
+ return;
+ }
+ mapZoomButtonController.setVisible(visibility == View.VISIBLE);
+ }
+
+ //
+ // Connectivity events
+ //
+
+ // This class handles connectivity changes
+ private class ConnectivityReceiver extends BroadcastReceiver {
+
+ // Called when an action we are listening to in the manifest has been sent
@Override
- public boolean onKeyLongPress(int keyCode, KeyEvent event) {
- // Check which key was pressed via hardware/real key code
- switch (keyCode) {
- // Tell the system to track these keys for long presses on
- // onKeyLongPress is fired
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return false;
- }
-
- // Zoom out
- zoom(false);
- return true;
-
- default:
- // We are not interested in this key
- return super.onKeyUp(keyCode, event);
- }
+ public void onReceive(Context context, Intent intent) {
+ if (!destroyed && intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+ nativeMapView.setReachability(!intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false));
+ }
+ }
+ }
+
+ // Called when MapView is being created
+ private boolean isConnected() {
+ ConnectivityManager connectivityManager = (ConnectivityManager)
+ getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
+ return (activeNetwork != null) && activeNetwork.isConnectedOrConnecting();
+ }
+
+ //
+ // Map events
+ //
+
+ /**
+ * <p>
+ * Add a callback that's invoked when the displayed map view changes.
+ * </p>
+ * To remove the callback, use {@link MapView#removeOnMapChangedListener(OnMapChangedListener)}.
+ *
+ * @param listener The callback that's invoked on every frame rendered to the map view.
+ * @see MapView#removeOnMapChangedListener(OnMapChangedListener)
+ */
+ public void addOnMapChangedListener(@Nullable OnMapChangedListener listener) {
+ if (listener != null) {
+ nativeMapView.addOnMapChangedListener(listener);
+ }
+ }
+
+ /**
+ * Remove a callback added with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}
+ *
+ * @param listener The previously added callback to remove.
+ * @see MapView#addOnMapChangedListener(OnMapChangedListener)
+ */
+ public void removeOnMapChangedListener(@Nullable OnMapChangedListener listener) {
+ if (listener != null) {
+ nativeMapView.removeOnMapChangedListener(listener);
+ }
+ }
+
+ /**
+ * Sets a callback object which will be triggered when the {@link MapboxMap} instance is ready to be used.
+ *
+ * @param callback The callback object that will be triggered when the map is ready to be used.
+ */
+ @UiThread
+ public void getMapAsync(final OnMapReadyCallback callback) {
+ if (!mapCallback.isInitialLoad() && callback != null) {
+ callback.onMapReady(mapboxMap);
+ } else {
+ if (callback != null) {
+ mapCallback.addOnMapReadyCallback(callback);
+ }
+ }
+ }
+
+ MapboxMap getMapboxMap() {
+ return mapboxMap;
+ }
+
+ void setMapboxMap(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ }
+
+ private static class AttributionOnClickListener implements View.OnClickListener, DialogInterface.OnClickListener {
+
+ private static final int ATTRIBUTION_INDEX_IMPROVE_THIS_MAP = 2;
+ private static final int ATTRIBUTION_INDEX_TELEMETRY_SETTINGS = 3;
+ private Context context;
+ private Transform transform;
+
+ public AttributionOnClickListener(Context context, Transform transform) {
+ this.context = context;
+ this.transform = transform;
+ }
+
+ // Called when someone presses the attribution icon
+ @Override
+ public void onClick(View view) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.mapbox_AlertDialogStyle);
+ builder.setTitle(R.string.mapbox_attributionsDialogTitle);
+ String[] items = context.getResources().getStringArray(R.array.mapbox_attribution_names);
+ builder.setAdapter(new ArrayAdapter<>(context, R.layout.mapbox_attribution_list_item, items), this);
+ builder.show();
}
- // Called when the user releases a key
+ // Called when someone selects an attribution, 'Improve this map' adds location data to the url
@Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- // Check if the key action was canceled (used for virtual keyboards)
- if (event.isCanceled()) {
- return super.onKeyUp(keyCode, event);
- }
-
- // Check which key was pressed via hardware/real key code
- // Note if keyboard does not have physical key (ie primary non-shifted
- // key) then it will not appear here
- // Must use the key character map as physical to character is not
- // fixed/guaranteed
- switch (keyCode) {
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return false;
- }
-
- // Zoom in
- zoom(true);
- return true;
- }
+ public void onClick(DialogInterface dialog, int which) {
+ final Context context = ((Dialog) dialog).getContext();
+ if (which == ATTRIBUTION_INDEX_TELEMETRY_SETTINGS) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.mapbox_AlertDialogStyle);
+ builder.setTitle(R.string.mapbox_attributionTelemetryTitle);
+ builder.setMessage(R.string.mapbox_attributionTelemetryMessage);
+ builder.setPositiveButton(R.string.mapbox_attributionTelemetryPositive, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(true);
+ dialog.cancel();
+ }
+ });
+ builder.setNeutralButton(R.string.mapbox_attributionTelemetryNeutral, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String url = context.getResources().getStringArray(R.array.mapbox_attribution_links)[3];
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(url));
+ context.startActivity(intent);
+ dialog.cancel();
+ }
+ });
+ builder.setNegativeButton(R.string.mapbox_attributionTelemetryNegative, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(false);
+ dialog.cancel();
+ }
+ });
- // We are not interested in this key
- return super.onKeyUp(keyCode, event);
- }
+ builder.show();
+ return;
+ }
+ String url = context.getResources().getStringArray(R.array.mapbox_attribution_links)[which];
+ if (which == ATTRIBUTION_INDEX_IMPROVE_THIS_MAP) {
+ CameraPosition cameraPosition = transform.getCameraPosition();
+ if (cameraPosition != null) {
+ url = String.format(url, cameraPosition.target.getLongitude(),
+ cameraPosition.target.getLatitude(), (int) cameraPosition.zoom);
+ }
+ }
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(url));
+ context.startActivity(intent);
+ }
+ }
+
+ /**
+ * Definition of a map change event.
+ *
+ * @see MapView.OnMapChangedListener#onMapChanged(int)
+ */
+ @IntDef( {REGION_WILL_CHANGE,
+ REGION_WILL_CHANGE_ANIMATED,
+ REGION_IS_CHANGING,
+ REGION_DID_CHANGE,
+ REGION_DID_CHANGE_ANIMATED,
+ WILL_START_LOADING_MAP,
+ DID_FINISH_LOADING_MAP,
+ DID_FAIL_LOADING_MAP,
+ WILL_START_RENDERING_FRAME,
+ DID_FINISH_RENDERING_FRAME,
+ DID_FINISH_RENDERING_FRAME_FULLY_RENDERED,
+ WILL_START_RENDERING_MAP,
+ DID_FINISH_RENDERING_MAP,
+ DID_FINISH_RENDERING_MAP_FULLY_RENDERED,
+ DID_FINISH_LOADING_STYLE,
+ SOURCE_DID_CHANGE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MapChange {
+ }
+
+ /**
+ * This event is triggered whenever the currently displayed map region is about to changing
+ * without an animation.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int REGION_WILL_CHANGE = 0;
+
+ /**
+ * This event is triggered whenever the currently displayed map region is about to changing
+ * with an animation.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int REGION_WILL_CHANGE_ANIMATED = 1;
+
+ /**
+ * This event is triggered whenever the currently displayed map region is changing.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int REGION_IS_CHANGING = 2;
+
+ /**
+ * This event is triggered whenever the currently displayed map region finished changing
+ * without an animation.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int REGION_DID_CHANGE = 3;
+
+ /**
+ * This event is triggered whenever the currently displayed map region finished changing
+ * with an animation.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int REGION_DID_CHANGE_ANIMATED = 4;
+
+ /**
+ * This event is triggered when the map is about to start loading a new map style.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int WILL_START_LOADING_MAP = 5;
+
+ /**
+ * This is triggered when the map has successfully loaded a new map style.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int DID_FINISH_LOADING_MAP = 6;
+
+ /**
+ * This event is triggered when the map has failed to load a new map style.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int DID_FAIL_LOADING_MAP = 7;
+
+ /**
+ * This event is triggered when the map will start rendering a frame.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int WILL_START_RENDERING_FRAME = 8;
+
+ /**
+ * This event is triggered when the map finished rendering a frame.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int DID_FINISH_RENDERING_FRAME = 9;
+
+ /**
+ * This event is triggered when the map finished rendeirng the frame fully.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int DID_FINISH_RENDERING_FRAME_FULLY_RENDERED = 10;
+
+ /**
+ * This event is triggered when the map will start rendering the map.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int WILL_START_RENDERING_MAP = 11;
+
+ /**
+ * This event is triggered when the map finished rendering the map.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int DID_FINISH_RENDERING_MAP = 12;
+
+ /**
+ * This event is triggered when the map is fully rendered.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int DID_FINISH_RENDERING_MAP_FULLY_RENDERED = 13;
+
+ /**
+ * This {@link MapChange} is triggered when a style has finished loading.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int DID_FINISH_LOADING_STYLE = 14;
+
+ /**
+ * This {@link MapChange} is triggered when a source attribution changes.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapChange
+ * @see MapView.OnMapChangedListener
+ */
+ public static final int SOURCE_DID_CHANGE = 15;
+
+ /**
+ * Interface definition for a callback to be invoked when the displayed map view changes.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
+ *
+ * @see MapView#addOnMapChangedListener(OnMapChangedListener)
+ * @see MapView.MapChange
+ */
+ public interface OnMapChangedListener {
+ /**
+ * Called when the displayed map view changes.
+ *
+ * @param change Type of map change event, one of {@link #REGION_WILL_CHANGE},
+ * {@link #REGION_WILL_CHANGE_ANIMATED},
+ * {@link #REGION_IS_CHANGING},
+ * {@link #REGION_DID_CHANGE},
+ * {@link #REGION_DID_CHANGE_ANIMATED},
+ * {@link #WILL_START_LOADING_MAP},
+ * {@link #DID_FAIL_LOADING_MAP},
+ * {@link #DID_FINISH_LOADING_MAP},
+ * {@link #WILL_START_RENDERING_FRAME},
+ * {@link #DID_FINISH_RENDERING_FRAME},
+ * {@link #DID_FINISH_RENDERING_FRAME_FULLY_RENDERED},
+ * {@link #WILL_START_RENDERING_MAP},
+ * {@link #DID_FINISH_RENDERING_MAP},
+ * {@link #DID_FINISH_RENDERING_MAP_FULLY_RENDERED}.
+ */
+ void onMapChanged(@MapChange int change);
+ }
+
+ private class FocalPointInvalidator implements FocalPointChangeListener {
- // Called for trackball events, all motions are relative in device specific
- // units
@Override
- public boolean onTrackballEvent(MotionEvent event) {
- if (destroyed) {
- return false;
- }
- // Choose the action
- switch (event.getActionMasked()) {
- // The trackball was rotated
- case MotionEvent.ACTION_MOVE:
- if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- // Cancel any animation
- nativeMapView.cancelTransitions();
-
- // Scroll the map
- nativeMapView.moveBy(-10.0 * event.getX() / screenDensity, -10.0 * event.getY() / screenDensity);
- return true;
-
- // Trackball was pushed in so start tracking and tell system we are
- // interested
- // We will then get the up action
- case MotionEvent.ACTION_DOWN:
- // Set up a delayed callback to check if trackball is still
- // After waiting the system long press time out
- if (currentTrackballLongPressTimeOut != null) {
- currentTrackballLongPressTimeOut.cancel();
- currentTrackballLongPressTimeOut = null;
- }
- currentTrackballLongPressTimeOut = new TrackballLongPressTimeOut();
- postDelayed(currentTrackballLongPressTimeOut,
- ViewConfiguration.getLongPressTimeout());
- return true;
-
- // Trackball was released
- case MotionEvent.ACTION_UP:
- if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return false;
- }
-
- // Only handle if we have not already long pressed
- if (currentTrackballLongPressTimeOut != null) {
- // Zoom in
- zoom(true);
- }
- return true;
-
- // Trackball was cancelled
- case MotionEvent.ACTION_CANCEL:
- if (currentTrackballLongPressTimeOut != null) {
- currentTrackballLongPressTimeOut.cancel();
- currentTrackballLongPressTimeOut = null;
- }
- return true;
-
- default:
- // We are not interested in this event
- return super.onTrackballEvent(event);
- }
+ public void onFocalPointChanged(PointF pointF) {
+ mapGestureDetector.setFocalPoint(pointF);
}
+ }
- // This class implements the trackball long press time out callback
- private class TrackballLongPressTimeOut implements Runnable {
-
- // Track if we have been cancelled
- private boolean cancelled;
-
- public TrackballLongPressTimeOut() {
- cancelled = false;
- }
+ private class RegisterTouchListener implements MapboxMap.OnRegisterTouchListener {
- // Cancel the timeout
- public void cancel() {
- cancelled = true;
- }
-
- // Called when long press time out expires
- @Override
- public void run() {
- // Check if the trackball is still pressed
- if (!cancelled) {
- // Zoom out
- zoom(false);
-
- // Ensure the up action is not run
- currentTrackballLongPressTimeOut = null;
- }
- }
- }
-
- // Called for events that don't fit the other handlers
- // such as mouse scroll events, mouse moves, joystick, trackpad
@Override
- public boolean onGenericMotionEvent(MotionEvent event) {
- if (destroyed) {
- return false;
- }
- // Mouse events
- //if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { // this is not available before API 18
- if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == InputDevice.SOURCE_CLASS_POINTER) {
- // Choose the action
- switch (event.getActionMasked()) {
- // Mouse scrolls
- case MotionEvent.ACTION_SCROLL:
- if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return false;
- }
-
- // Cancel any animation
- nativeMapView.cancelTransitions();
-
- // Get the vertical scroll amount, one click = 1
- float scrollDist = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
-
- // Scale the map by the appropriate power of two factor
- nativeMapView.scaleBy(Math.pow(2.0, scrollDist), event.getX() / screenDensity, event.getY() / screenDensity);
-
- return true;
-
- default:
- // We are not interested in this event
- return super.onGenericMotionEvent(event);
- }
- }
-
- // We are not interested in this event
- return super.onGenericMotionEvent(event);
+ public void onRegisterMapClickListener(MapboxMap.OnMapClickListener listener) {
+ mapGestureDetector.setOnMapClickListener(listener);
}
- // Called when the mouse pointer enters or exits the view
- // or when it fades in or out due to movement
@Override
- public boolean onHoverEvent(@NonNull MotionEvent event) {
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_HOVER_ENTER:
- case MotionEvent.ACTION_HOVER_MOVE:
- // Show the zoom controls
- if (mapboxMap.getUiSettings().isZoomControlsEnabled()) {
- zoomButtonsController.setVisible(true);
- }
- return true;
-
- case MotionEvent.ACTION_HOVER_EXIT:
- // Hide the zoom controls
- if (mapboxMap.getUiSettings().isZoomControlsEnabled()) {
- zoomButtonsController.setVisible(false);
- }
- return true;
-
- default:
- // We are not interested in this event
- return super.onHoverEvent(event);
- }
- }
-
- //
- // Connectivity events
- //
-
- // This class handles connectivity changes
- private class ConnectivityReceiver extends BroadcastReceiver {
-
- // Called when an action we are listening to in the manifest has been sent
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
- boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
- onConnectivityChanged(!noConnectivity);
- }
- }
- }
-
- // Called when MapView is being created
- private boolean isConnected() {
- Context appContext = getContext().getApplicationContext();
- ConnectivityManager connectivityManager = (ConnectivityManager) appContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
- return (activeNetwork != null) && activeNetwork.isConnectedOrConnecting();
+ public void onRegisterMapLongClickListener(MapboxMap.OnMapLongClickListener listener) {
+ mapGestureDetector.setOnMapLongClickListener(listener);
}
- // Called when our Internet connectivity has changed
- private void onConnectivityChanged(boolean isConnected) {
- nativeMapView.setReachability(isConnected);
- }
-
- //
- // Map events
- //
-
- /**
- * <p>
- * Add a callback that's invoked when the displayed map view changes.
- * </p>
- * To remove the callback, use {@link MapView#removeOnMapChangedListener(OnMapChangedListener)}.
- *
- * @param listener The callback that's invoked on every frame rendered to the map view.
- * @see MapView#removeOnMapChangedListener(OnMapChangedListener)
- */
- public void addOnMapChangedListener(@Nullable OnMapChangedListener listener) {
- if (listener != null) {
- onMapChangedListener.add(listener);
- }
- }
-
- /**
- * Remove a callback added with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}
- *
- * @param listener The previously added callback to remove.
- * @see MapView#addOnMapChangedListener(OnMapChangedListener)
- */
- public void removeOnMapChangedListener(@Nullable OnMapChangedListener listener) {
- if (listener != null) {
- onMapChangedListener.remove(listener);
- }
- }
-
- // Called when the map view transformation has changed
- // Called via JNI from NativeMapView
- // Forward to any listeners
- protected void onMapChanged(int mapChange) {
- if (onMapChangedListener != null) {
- OnMapChangedListener listener;
- final Iterator<OnMapChangedListener> iterator = onMapChangedListener.iterator();
- while (iterator.hasNext()) {
- listener = iterator.next();
- listener.onMapChanged(mapChange);
- }
- }
- }
-
- //
- // User location
- //
-
- void setMyLocationEnabled(boolean enabled) {
- myLocationView.setEnabled(enabled);
- }
-
- Location getMyLocation() {
- return myLocationView.getLocation();
- }
-
- void setOnMyLocationChangeListener(@Nullable final MapboxMap.OnMyLocationChangeListener listener) {
- if (listener != null) {
- myLocationListener = new LocationListener() {
- @Override
- public void onLocationChanged(Location location) {
- if (listener != null) {
- listener.onMyLocationChange(location);
- }
- }
- };
- LocationServices.getLocationServices(getContext()).addLocationListener(myLocationListener);
- } else {
- LocationServices.getLocationServices(getContext()).removeLocationListener(myLocationListener);
- myLocationListener = null;
- }
- }
-
- void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
- if (myLocationTrackingMode != MyLocationTracking.TRACKING_NONE && !mapboxMap.isMyLocationEnabled()) {
- mapboxMap.setMyLocationEnabled(true);
- }
- myLocationView.setMyLocationTrackingMode(myLocationTrackingMode);
-
- if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
- setFocalPoint(new PointF(myLocationView.getCenterX(), myLocationView.getCenterY()));
- } else {
- setFocalPoint(null);
- }
-
- MapboxMap.OnMyLocationTrackingModeChangeListener listener = mapboxMap.getOnMyLocationTrackingModeChangeListener();
- if (listener != null) {
- listener.onMyLocationTrackingModeChange(myLocationTrackingMode);
- }
- }
-
- void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) {
- if (myBearingTrackingMode != MyBearingTracking.NONE && !mapboxMap.isMyLocationEnabled()) {
- mapboxMap.setMyLocationEnabled(true);
- }
- myLocationView.setMyBearingTrackingMode(myBearingTrackingMode);
- MapboxMap.OnMyBearingTrackingModeChangeListener listener = mapboxMap.getOnMyBearingTrackingModeChangeListener();
- if (listener != null) {
- listener.onMyBearingTrackingModeChange(myBearingTrackingMode);
- }
- }
-
- boolean isPermissionsAccepted() {
- return (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) ||
- ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
- }
-
- /**
- * Reset the tracking modes as necessary. Location tracking is reset if the map center is changed,
- * bearing tracking if there is a rotation.
- *
- * @param translate
- * @param rotate
- */
- void resetTrackingModesIfRequired(boolean translate, boolean rotate) {
- TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
-
- // if tracking is on, and we should dismiss tracking with gestures, and this is a scroll action, turn tracking off
- if (translate && !trackingSettings.isLocationTrackingDisabled() && trackingSettings.isDismissLocationTrackingOnGesture()) {
- resetLocationTrackingMode();
- }
-
- // reset bearing tracking only on rotate
- if (rotate && !trackingSettings.isBearingTrackingDisabled() && trackingSettings.isDismissBearingTrackingOnGesture()) {
- resetBearingTrackingMode();
- }
- }
-
- void resetTrackingModesIfRequired(CameraPosition cameraPosition) {
- resetTrackingModesIfRequired(cameraPosition.target != null, cameraPosition.bearing != -1);
- }
-
- private void resetLocationTrackingMode() {
- try {
- TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
- trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE);
- } catch (SecurityException ignore) {
- // User did not accept location permissions
- }
- }
-
- private void resetBearingTrackingMode() {
- try {
- TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
- trackingSettings.setMyBearingTrackingMode(MyBearingTracking.NONE);
- } catch (SecurityException ignore) {
- // User did not accept location permissions
- }
- }
-
- //
- // Compass
- //
-
- void setCompassEnabled(boolean compassEnabled) {
- compassView.setEnabled(compassEnabled);
- }
-
- void setCompassGravity(int gravity) {
- setWidgetGravity(compassView, gravity);
- }
-
- void setCompassMargins(int left, int top, int right, int bottom) {
- setWidgetMargins(compassView, left, top, right, bottom);
- }
-
- void setCompassFadeFacingNorth(boolean compassFadeFacingNorth) {
- compassView.fadeCompassViewFacingNorth(compassFadeFacingNorth);
- }
-
- //
- // Logo
- //
-
- void setLogoGravity(int gravity) {
- setWidgetGravity(logoView, gravity);
- }
-
- void setLogoMargins(int left, int top, int right, int bottom) {
- setWidgetMargins(logoView, left, top, right, bottom);
- }
-
- void setLogoEnabled(boolean visible) {
- logoView.setVisibility(visible ? View.VISIBLE : View.GONE);
- }
-
- //
- // Attribution
- //
-
- void setAttributionGravity(int gravity) {
- setWidgetGravity(attributionsView, gravity);
- }
-
- void setAttributionMargins(int left, int top, int right, int bottom) {
- setWidgetMargins(attributionsView, left, top, right, bottom);
- }
-
- void setAttributionEnabled(int visibility) {
- attributionsView.setVisibility(visibility);
- }
-
- void setAtttibutionTintColor(int tintColor) {
- ColorUtils.setTintList(attributionsView, tintColor);
- }
-
- int getAttributionTintColor() {
- return mapboxMap.getUiSettings().getAttributionTintColor();
- }
-
- /**
- * Sets a callback object which will be triggered when the {@link MapboxMap} instance is ready to be used.
- *
- * @param callback The callback object that will be triggered when the map is ready to be used.
- */
- @UiThread
- public void getMapAsync(final OnMapReadyCallback callback) {
- if (!initialLoad && callback != null) {
- callback.onMapReady(mapboxMap);
- } else {
- if (callback != null) {
- onMapReadyCallbackList.add(callback);
- }
- }
- }
-
- MapboxMap getMapboxMap() {
- return mapboxMap;
- }
-
- void setMapboxMap(MapboxMap mapboxMap) {
- this.mapboxMap = mapboxMap;
- }
-
- MyLocationView getUserLocationView() {
- return myLocationView;
- }
-
- NativeMapView getNativeMapView() {
- return nativeMapView;
- }
-
- //
- // Snapshot API
- //
-
- @UiThread
- void snapshot(@NonNull final MapboxMap.SnapshotReadyCallback callback, @Nullable final Bitmap bitmap) {
- snapshotRequest = new SnapshotRequest(bitmap, callback);
- nativeMapView.scheduleTakeSnapshot();
- nativeMapView.render();
- }
-
- // Called when the snapshot method was executed
- // Called via JNI from NativeMapView
- // Forward to any listeners
- protected void onSnapshotReady(byte[] bytes) {
- if (snapshotRequest != null && bytes != null) {
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inBitmap = snapshotRequest.getBitmap(); // the old Bitmap to be reused
- options.inMutable = true;
- options.inSampleSize = 1;
- Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
-
- MapboxMap.SnapshotReadyCallback callback = snapshotRequest.getCallback();
- if (callback != null) {
- callback.onSnapshotReady(bitmap);
- }
- }
+ @Override
+ public void onRegisterScrollListener(MapboxMap.OnScrollListener listener) {
+ mapGestureDetector.setOnScrollListener(listener);
}
- private class SnapshotRequest {
- private Bitmap bitmap;
- private MapboxMap.SnapshotReadyCallback callback;
-
- public SnapshotRequest(Bitmap bitmap, MapboxMap.SnapshotReadyCallback callback) {
- this.bitmap = bitmap;
- this.callback = callback;
- }
-
- public Bitmap getBitmap() {
- return bitmap;
- }
-
- public MapboxMap.SnapshotReadyCallback getCallback() {
- return callback;
- }
+ @Override
+ public void onRegisterFlingListener(MapboxMap.OnFlingListener listener) {
+ mapGestureDetector.setOnFlingListener(listener);
}
+ }
- //
- // View utility methods
- //
+ private static class MapCallback implements OnMapChangedListener {
- private void setWidgetGravity(@NonNull final View view, int gravity) {
- LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
- layoutParams.gravity = gravity;
- view.setLayoutParams(layoutParams);
- }
+ private final MapboxMap mapboxMap;
+ private final List<OnMapReadyCallback> onMapReadyCallbackList = new ArrayList<>();
+ private boolean initialLoad = true;
- private void setWidgetMargins(@NonNull final View view, int left, int top, int right, int bottom) {
- LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
- left += contentPaddingLeft;
- top += contentPaddingTop;
- right += contentPaddingRight;
- bottom += contentPaddingBottom;
- layoutParams.setMargins(left, top, right, bottom);
- view.setLayoutParams(layoutParams);
+ MapCallback(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
}
- private static class AttributionOnClickListener implements View.OnClickListener, DialogInterface.OnClickListener {
-
- private static final int ATTRIBUTION_INDEX_IMPROVE_THIS_MAP = 2;
- private static final int ATTRIBUTION_INDEX_TELEMETRY_SETTINGS = 3;
- private MapView mapView;
-
- public AttributionOnClickListener(MapView mapView) {
- super();
- this.mapView = mapView;
- }
-
- // Called when someone presses the attribution icon
- @Override
- public void onClick(View view) {
-
- AlertDialog.Builder builder = new AlertDialog.Builder(mapView.getContext(), R.style.TelemAlertDialogStyle);
- builder.setTitle(R.string.attributionsDialogTitle);
- String[] items = mapView.getContext().getResources().getStringArray(R.array.attribution_names);
- builder.setAdapter(new ArrayAdapter<>(mapView.getContext(), R.layout.attribution_list_item, items), this);
- AlertDialog attributionDialog = builder.show();
-
- // TODO Change listview text color to mapView.getAttributionTintColor()
- }
-
- // Called when someone selects an attribution, 'Improve this map' adds location data to the url
- @Override
- public void onClick(DialogInterface dialog, int which) {
- final Context context = ((Dialog) dialog).getContext();
- if (which == ATTRIBUTION_INDEX_TELEMETRY_SETTINGS) {
- AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.TelemAlertDialogStyle);
- builder.setTitle(R.string.attributionTelemetryTitle);
- builder.setMessage(R.string.attributionTelemetryMessage);
- builder.setPositiveButton(R.string.attributionTelemetryPositive, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(true);
- dialog.cancel();
- }
- });
- builder.setNeutralButton(R.string.attributionTelemetryNeutral, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- String url = context.getResources().getStringArray(R.array.attribution_links)[3];
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(url));
- context.startActivity(intent);
- dialog.cancel();
- }
- });
- builder.setNegativeButton(R.string.attributionTelemetryNegative, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(false);
- dialog.cancel();
- }
- });
-
- AlertDialog telemDialog = builder.show();
- telemDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(mapView.getAttributionTintColor());
- telemDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(mapView.getAttributionTintColor());
- telemDialog.getButton(AlertDialog.BUTTON_NEUTRAL).setTextColor(mapView.getAttributionTintColor());
- return;
- }
- String url = context.getResources().getStringArray(R.array.attribution_links)[which];
- if (which == ATTRIBUTION_INDEX_IMPROVE_THIS_MAP) {
- LatLng latLng = mapView.getMapboxMap().getCameraPosition().target;
- url = String.format(url, latLng.getLongitude(), latLng.getLatitude(), (int) mapView.getZoom());
- }
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(url));
- context.startActivity(intent);
- }
+ @Override
+ public void onMapChanged(@MapChange int change) {
+ if (change == DID_FINISH_LOADING_STYLE && initialLoad) {
+ initialLoad = false;
+ mapboxMap.onPreMapReady();
+ onMapReady();
+ mapboxMap.onPostMapReady();
+ } else if (change == REGION_IS_CHANGING || change == REGION_DID_CHANGE || change == DID_FINISH_LOADING_MAP) {
+ mapboxMap.onUpdate();
+ }
}
- private static class ZoomInvalidator implements Runnable {
-
- private MapboxMap mapboxMap;
-
- public ZoomInvalidator(MapboxMap mapboxMap) {
- this.mapboxMap = mapboxMap;
- }
-
- @Override
- public void run() {
- // invalidate camera position
- mapboxMap.getCameraPosition();
+ private void onMapReady() {
+ if (onMapReadyCallbackList.size() > 0) {
+ // Notify listeners, clear when done
+ Iterator<OnMapReadyCallback> iterator = onMapReadyCallbackList.iterator();
+ while (iterator.hasNext()) {
+ OnMapReadyCallback callback = iterator.next();
+ callback.onMapReady(mapboxMap);
+ iterator.remove();
}
+ }
}
- /**
- * Definition of a map change event.
- *
- * @see MapView.OnMapChangedListener#onMapChanged(int)
- */
- @IntDef({REGION_WILL_CHANGE,
- REGION_WILL_CHANGE_ANIMATED,
- REGION_IS_CHANGING,
- REGION_DID_CHANGE,
- REGION_DID_CHANGE_ANIMATED,
- WILL_START_LOADING_MAP,
- DID_FINISH_LOADING_MAP,
- DID_FAIL_LOADING_MAP,
- WILL_START_RENDERING_FRAME,
- DID_FINISH_RENDERING_FRAME,
- DID_FINISH_RENDERING_FRAME_FULLY_RENDERED,
- WILL_START_RENDERING_MAP,
- DID_FINISH_RENDERING_MAP,
- DID_FINISH_RENDERING_MAP_FULLY_RENDERED,
- DID_FINISH_LOADING_STYLE
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface MapChange {
+ boolean isInitialLoad() {
+ return initialLoad;
}
- /**
- * This event is triggered whenever the currently displayed map region is about to changing
- * without an animation.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int REGION_WILL_CHANGE = 0;
-
- /**
- * This event is triggered whenever the currently displayed map region is about to changing
- * with an animation.
- * <p
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int REGION_WILL_CHANGE_ANIMATED = 1;
-
- /**
- * This event is triggered whenever the currently displayed map region is changing.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int REGION_IS_CHANGING = 2;
-
- /**
- * This event is triggered whenever the currently displayed map region finished changing
- * without an animation.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int REGION_DID_CHANGE = 3;
-
- /**
- * This event is triggered whenever the currently displayed map region finished changing
- * with an animation.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int REGION_DID_CHANGE_ANIMATED = 4;
-
- /**
- * This event is triggered when the map is about to start loading a new map style.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int WILL_START_LOADING_MAP = 5;
-
- /**
- * This is triggered when the map has successfully loaded a new map style.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int DID_FINISH_LOADING_MAP = 6;
-
- /**
- * This event is triggered when the map has failed to load a new map style.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int DID_FAIL_LOADING_MAP = 7;
-
- /**
- * This event is triggered when the map will start rendering a frame.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int WILL_START_RENDERING_FRAME = 8;
-
- /**
- * This event is triggered when the map finished rendering a frame.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int DID_FINISH_RENDERING_FRAME = 9;
-
- /**
- * This event is triggered when the map finished rendeirng the frame fully.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int DID_FINISH_RENDERING_FRAME_FULLY_RENDERED = 10;
-
- /**
- * This event is triggered when the map will start rendering the map.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int WILL_START_RENDERING_MAP = 11;
-
- /**
- * This event is triggered when the map finished rendering the map.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int DID_FINISH_RENDERING_MAP = 12;
-
- /**
- * This event is triggered when the map is fully rendered.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int DID_FINISH_RENDERING_MAP_FULLY_RENDERED = 13;
-
-
- /**
- * This {@link MapChange} is triggered when a style has finished loading.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapChange
- * @see MapView.OnMapChangedListener
- */
- public static final int DID_FINISH_LOADING_STYLE = 14;
-
- /**
- * Interface definition for a callback to be invoked when the displayed map view changes.
- * <p>
- * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
- * </p>
- *
- * @see MapView#addOnMapChangedListener(OnMapChangedListener)
- * @see MapView.MapChange
- */
- public interface OnMapChangedListener {
- /**
- * Called when the displayed map view changes.
- *
- * @param change Type of map change event, one of {@link #REGION_WILL_CHANGE},
- * {@link #REGION_WILL_CHANGE_ANIMATED},
- * {@link #REGION_IS_CHANGING},
- * {@link #REGION_DID_CHANGE},
- * {@link #REGION_DID_CHANGE_ANIMATED},
- * {@link #WILL_START_LOADING_MAP},
- * {@link #DID_FAIL_LOADING_MAP},
- * {@link #DID_FINISH_LOADING_MAP},
- * {@link #WILL_START_RENDERING_FRAME},
- * {@link #DID_FINISH_RENDERING_FRAME},
- * {@link #DID_FINISH_RENDERING_FRAME_FULLY_RENDERED},
- * {@link #WILL_START_RENDERING_MAP},
- * {@link #DID_FINISH_RENDERING_MAP},
- * {@link #DID_FINISH_RENDERING_MAP_FULLY_RENDERED}.
- */
- void onMapChanged(@MapChange int change);
+ void addOnMapReadyCallback(OnMapReadyCallback callback) {
+ onMapReadyCallbackList.add(callback);
}
-
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapZoomButtonController.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapZoomButtonController.java
new file mode 100644
index 0000000000..06084d906e
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapZoomButtonController.java
@@ -0,0 +1,59 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.support.annotation.NonNull;
+import android.view.View;
+import android.widget.ZoomButtonsController;
+
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+
+/**
+ * The MapZoomButtonController is a ui interface element shown on top of the map.
+ * <p>
+ * Allows single touch only devices to zoom in and out.
+ * </p>
+ */
+final class MapZoomButtonController extends ZoomButtonsController {
+
+ private UiSettings uiSettings;
+
+ MapZoomButtonController(@NonNull View ownerView, @NonNull UiSettings uiSettings, @NonNull Transform transform) {
+ super(ownerView);
+ this.uiSettings = uiSettings;
+ setZoomSpeed(MapboxConstants.ANIMATION_DURATION);
+ setOnZoomListener(new OnZoomListener(uiSettings, transform));
+ }
+
+ @Override
+ public void setVisible(boolean visible) {
+ if (uiSettings.isZoomControlsEnabled()) {
+ super.setVisible(visible);
+ }
+ }
+
+ // Zoom controls allow single touch only devices to zoom in and out
+ private static class OnZoomListener implements ZoomButtonsController.OnZoomListener {
+
+ private final UiSettings uiSettings;
+ private final Transform transform;
+
+ OnZoomListener(UiSettings uiSettings, Transform transform) {
+ this.uiSettings = uiSettings;
+ this.transform = transform;
+ }
+
+ // Not used
+ @Override
+ public void onVisibilityChanged(boolean visible) {
+ // Ignore
+ }
+
+ // Called when user pushes a zoom button
+ @Override
+ public void onZoom(boolean zoomIn) {
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return;
+ }
+ transform.zoom(zoomIn);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
index b1f0984e3c..f460a77229 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
@@ -5,24 +5,21 @@ import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.RectF;
import android.location.Location;
-import android.os.SystemClock;
+import android.os.Bundle;
+import android.os.Handler;
import android.support.annotation.FloatRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
-import android.support.v4.util.LongSparseArray;
import android.support.v4.util.Pools;
import android.text.TextUtils;
-import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
-import com.mapbox.mapboxsdk.MapboxAccountManager;
+import com.mapbox.mapboxsdk.Mapbox;
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.InfoWindow;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.annotations.MarkerView;
@@ -47,9 +44,9 @@ import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.services.commons.geojson.Feature;
import java.lang.reflect.ParameterizedType;
-import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.TimeUnit;
+
+import timber.log.Timber;
/**
* The general class to interact with in the Android Mapbox SDK. It exposes the entry point for all
@@ -60,2165 +57,1934 @@ import java.util.concurrent.TimeUnit;
* Note: Similar to a View object, a MapboxMap should only be read and modified from the main thread.
* </p>
*/
-public class MapboxMap {
- private static final String TAG = MapboxMap.class.getSimpleName();
-
- private MapView mapView;
- private UiSettings uiSettings;
- private TrackingSettings trackingSettings;
- private MyLocationViewSettings myLocationViewSettings;
- private Projection projection;
- private CameraPosition cameraPosition;
- private boolean invalidCameraPosition;
- private LongSparseArray<Annotation> annotations;
-
- private List<Marker> selectedMarkers;
- private MarkerViewManager markerViewManager;
-
- private List<InfoWindow> infoWindows;
- private MapboxMap.InfoWindowAdapter infoWindowAdapter;
-
- private boolean myLocationEnabled;
- private boolean allowConcurrentMultipleInfoWindows;
-
- private MapboxMap.OnMapClickListener onMapClickListener;
- private MapboxMap.OnMapLongClickListener onMapLongClickListener;
- private MapboxMap.OnMarkerClickListener onMarkerClickListener;
- private MapboxMap.OnInfoWindowClickListener onInfoWindowClickListener;
- private MapboxMap.OnInfoWindowLongClickListener onInfoWindowLongClickListener;
- private MapboxMap.OnInfoWindowCloseListener onInfoWindowCloseListener;
- private MapboxMap.OnFlingListener onFlingListener;
- private MapboxMap.OnScrollListener onScrollListener;
- private MapboxMap.OnMyLocationTrackingModeChangeListener onMyLocationTrackingModeChangeListener;
- private MapboxMap.OnMyBearingTrackingModeChangeListener onMyBearingTrackingModeChangeListener;
- private MapboxMap.OnFpsChangedListener onFpsChangedListener;
- private MapboxMap.OnCameraChangeListener onCameraChangeListener;
-
- private double maxZoomLevel = -1;
- private double minZoomLevel = -1;
-
- MapboxMap(@NonNull MapView mapView) {
- this.mapView = mapView;
- this.mapView.addOnMapChangedListener(new MapChangeCameraPositionListener());
- uiSettings = new UiSettings(mapView);
- trackingSettings = new TrackingSettings(this.mapView, uiSettings);
- projection = new Projection(mapView);
- annotations = new LongSparseArray<>();
- selectedMarkers = new ArrayList<>();
- infoWindows = new ArrayList<>();
- markerViewManager = new MarkerViewManager(this, mapView);
- }
-
- // Style
-
- @Nullable
- @UiThread
- public Layer getLayer(@NonNull String layerId) {
- return getMapView().getNativeMapView().getLayer(layerId);
- }
-
- /**
- * Tries to cast the Layer to T, returns null if it's another type.
- *
- * @param layerId the layer id used to look up a layer
- * @param <T> the generic attribute of a Layer
- * @return the casted Layer, null if another type
- */
- @Nullable
- @UiThread
- public <T extends Layer> T getLayerAs(@NonNull String layerId) {
- try {
- //noinspection unchecked
- return (T) getMapView().getNativeMapView().getLayer(layerId);
- } catch (ClassCastException e) {
- Log.e(TAG, String.format("Layer: %s is a different type: %s", layerId, e.getMessage()));
- return null;
- }
- }
-
- @UiThread
- public void addLayer(@NonNull Layer layer) {
- addLayer(layer, null);
- }
-
- @UiThread
- public void addLayer(@NonNull Layer layer, String before) {
- getMapView().getNativeMapView().addLayer(layer, before);
- }
-
- @UiThread
- public void removeLayer(@NonNull String layerId) throws NoSuchLayerException {
- getMapView().getNativeMapView().removeLayer(layerId);
- }
-
- @Nullable
- @UiThread
- public Source getSource(@NonNull String sourceId) {
- return getMapView().getNativeMapView().getSource(sourceId);
- }
-
- /**
- * Tries to cast the Source to T, returns null if it's another type.
- *
- * @param sourceId the id used to look up a layer
- * @param <T> the generic type of a Source
- * @return the casted Source, null if another type
- */
- @Nullable
- @UiThread
- public <T extends Source> T getSourceAs(@NonNull String sourceId) {
- try {
- //noinspection unchecked
- return (T) getMapView().getNativeMapView().getSource(sourceId);
- } catch (ClassCastException e) {
- Log.e(TAG, String.format("Source: %s is a different type: %s", sourceId, e.getMessage()));
- return null;
- }
- }
-
- @UiThread
- public void addSource(@NonNull Source source) {
- getMapView().getNativeMapView().addSource(source);
- }
-
- @UiThread
- public void removeSource(@NonNull String sourceId) throws NoSuchSourceException {
- getMapView().getNativeMapView().removeSource(sourceId);
- }
-
- /**
- * Add an image to be used int hte map's style
- *
- * @param name the name of the image
- * @param image the pre-multiplied Bitmap
- */
- @UiThread
- public void addImage(@NonNull String name, @NonNull Bitmap image) {
- getMapView().getNativeMapView().addImage(name, image);
- }
-
- /**
- * Removes an image from the map's style
- *
- * @param name the name of the image to remove
- */
- @UiThread
- public void removeImage(String name) {
- getMapView().getNativeMapView().removeImage(name);
- }
-
- //
- // MinZoom
- //
-
- /**
- * <p>
- * Sets the minimum zoom level the map can be displayed at.
- * </p>
- *
- * @param minZoom The new minimum zoom level.
- */
- @UiThread
- public void setMinZoom(
- @FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) {
- if ((minZoom < MapboxConstants.MINIMUM_ZOOM) || (minZoom > MapboxConstants.MAXIMUM_ZOOM)) {
- Log.e(MapboxConstants.TAG, "Not setting minZoom, value is in unsupported range: " + minZoom);
- return;
- }
- minZoomLevel = minZoom;
- mapView.setMinZoom(minZoom);
- }
-
- /**
- * <p>
- * Gets the maximum zoom level the map can be displayed at.
- * </p>
- *
- * @return The minimum zoom level.
- */
- @UiThread
- public double getMinZoom() {
- if (minZoomLevel == -1) {
- return minZoomLevel = mapView.getMinZoom();
- }
- return minZoomLevel;
- }
-
- //
- // MaxZoom
- //
-
- /**
- * <p>
- * Sets the maximum zoom level the map can be displayed at.
- * </p>
- *
- * @param maxZoom The new maximum zoom level.
- */
- @UiThread
- public void setMaxZoom(
- @FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) {
- if ((maxZoom < MapboxConstants.MINIMUM_ZOOM) || (maxZoom > MapboxConstants.MAXIMUM_ZOOM)) {
- Log.e(MapboxConstants.TAG, "Not setting maxZoom, value is in unsupported range: " + maxZoom);
- return;
- }
- maxZoomLevel = maxZoom;
- mapView.setMaxZoom(maxZoom);
- }
-
- /**
- * <p>
- * Gets the maximum zoom level the map can be displayed at.
- * </p>
- *
- * @return The maximum zoom level.
- */
- @UiThread
- public double getMaxZoom() {
- if (maxZoomLevel == -1) {
- return maxZoomLevel = mapView.getMaxZoom();
- }
- return maxZoomLevel;
- }
-
- //
- // UiSettings
- //
-
- /**
- * Gets the user interface settings for the map.
- *
- * @return the UiSettings associated with this map
- */
- public UiSettings getUiSettings() {
- return uiSettings;
- }
-
- //
- // TrackingSettings
- //
-
- /**
- * Gets the tracking interface settings for the map.
- *
- * @return the TrackingSettings asssociated with this map
- */
- public TrackingSettings getTrackingSettings() {
- return trackingSettings;
- }
-
- //
- // MyLocationViewSettings
- //
-
- /**
- * Gets the settings of the user location for the map.
- *
- * @return the MyLocationViewSettings associated with this map
- */
- public MyLocationViewSettings getMyLocationViewSettings() {
- if (myLocationViewSettings == null) {
- myLocationViewSettings = new MyLocationViewSettings(mapView, mapView.getUserLocationView());
- }
- return myLocationViewSettings;
- }
-
- //
- // Projection
- //
-
- /**
- * Get the Projection object that you can use to convert between screen coordinates and latitude/longitude
- * coordinates.
- *
- * @return the Projection associated with this map
- */
- public Projection getProjection() {
- return projection;
- }
-
- //
- // Camera API
- //
-
- /**
- * Gets the current position of the camera.
- * The CameraPosition returned is a snapshot of the current position, and will not automatically update when the
- * camera moves.
- *
- * @return The current position of the Camera.
- */
- public final CameraPosition getCameraPosition() {
- if (invalidCameraPosition) {
- invalidateCameraPosition();
- }
- return cameraPosition;
- }
-
- /**
- * Repositions the camera according to the cameraPosition.
- * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position.
- * See CameraUpdateFactory for a set of updates.
- *
- * @param cameraPosition the camera position to set
- */
- public void setCameraPosition(@NonNull CameraPosition cameraPosition) {
- moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
- }
-
- /**
- * Repositions the camera according to the instructions defined in the update.
- * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position.
- * See CameraUpdateFactory for a set of updates.
- *
- * @param update The change that should be applied to the camera.
- */
- @UiThread
- public final void moveCamera(CameraUpdate update) {
- moveCamera(update, null);
- }
-
- /**
- * Repositions the camera according to the instructions defined in the update.
- * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position.
- * See CameraUpdateFactory for a set of updates.
- *
- * @param update The change that should be applied to the camera
- * @param callback the callback to be invoked when an animation finishes or is canceled
- */
- @UiThread
- public final void moveCamera(CameraUpdate update, MapboxMap.CancelableCallback callback) {
- cameraPosition = update.getCameraPosition(this);
- mapView.resetTrackingModesIfRequired(cameraPosition);
- mapView.jumpTo(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom);
- if (callback != null) {
- callback.onFinish();
- }
-
- if (onCameraChangeListener != null) {
- onCameraChangeListener.onCameraChange(this.cameraPosition);
- }
- }
-
- /**
- * Gradually move the camera by the default duration, zoom will not be affected unless specified
- * within {@link CameraUpdate}. If {@link #getCameraPosition()} is called during the animation,
- * it will return the current location of the camera in flight.
- *
- * @param update The change that should be applied to the camera.
- * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
- */
- @UiThread
- public final void easeCamera(CameraUpdate update) {
- easeCamera(update, MapboxConstants.ANIMATION_DURATION);
- }
-
- /**
- * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected
- * unless specified within {@link CameraUpdate}. If {@link #getCameraPosition()} is called
- * during the animation, it will return the current location of the camera in flight.
- *
- * @param update The change that should be applied to the camera.
- * @param durationMs The duration of the animation in milliseconds. This must be strictly
- * positive, otherwise an IllegalArgumentException will be thrown.
- * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
- */
- @UiThread
- public final void easeCamera(CameraUpdate update, int durationMs) {
- easeCamera(update, durationMs, null);
- }
-
- /**
- * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected
- * unless specified within {@link CameraUpdate}. A callback can be used to be notified when
- * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it
- * will return the current location of the camera in flight.
- * <p>
- * Note that this will cancel location tracking mode if enabled.
- * </p>
- *
- * @param update The change that should be applied to the camera.
- * @param durationMs The duration of the animation in milliseconds. This must be strictly
- * positive, otherwise an IllegalArgumentException will be thrown.
- * @param callback An optional callback to be notified from the main thread when the animation
- * stops. If the animation stops due to its natural completion, the callback
- * will be notified with onFinish(). If the animation stops due to interruption
- * by a later camera movement or a user gesture, onCancel() will be called.
- * Do not update or ease the camera from within onCancel().
- * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
- */
- @UiThread
- public final void easeCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) {
- easeCamera(update, durationMs, true, callback);
- }
-
- @UiThread
- public final void easeCamera(CameraUpdate update, int durationMs, boolean easingInterpolator) {
- easeCamera(update, durationMs, easingInterpolator, null);
- }
-
- @UiThread
- public final void easeCamera(
- CameraUpdate update, int durationMs, boolean easingInterpolator, final MapboxMap.CancelableCallback callback) {
- // dismiss tracking, moving camera is equal to a gesture
- easeCamera(update, durationMs, easingInterpolator, true, callback);
- }
-
- @UiThread
- public final void easeCamera(
- CameraUpdate update, int durationMs, boolean easingInterpolator, boolean resetTrackingMode, final MapboxMap.CancelableCallback callback) {
- // dismiss tracking, moving camera is equal to a gesture
- cameraPosition = update.getCameraPosition(this);
- if (resetTrackingMode) {
- mapView.resetTrackingModesIfRequired(cameraPosition);
- }
-
- mapView.easeTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt,
- cameraPosition.zoom, easingInterpolator, new CancelableCallback() {
- @Override
- public void onCancel() {
- if (callback != null) {
- callback.onCancel();
- }
- invalidateCameraPosition();
- }
-
- @Override
- public void onFinish() {
- if (callback != null) {
- callback.onFinish();
- }
- invalidateCameraPosition();
- }
- });
- }
-
- /**
- * Animate the camera to a new location defined within {@link CameraUpdate} using a transition
- * animation that evokes powered flight. The animation will last the default amount of time.
- * During the animation, a call to {@link #getCameraPosition()} returns an intermediate location
- * of the camera in flight.
- *
- * @param update The change that should be applied to the camera.
- * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
- */
- @UiThread
- public final void animateCamera(CameraUpdate update) {
- animateCamera(update, MapboxConstants.ANIMATION_DURATION, null);
- }
-
- /**
- * Animate the camera to a new location defined within {@link CameraUpdate} using a transition
- * animation that evokes powered flight. The animation will last the default amount of time. A
- * callback can be used to be notified when animating the camera stops. During the animation, a
- * call to {@link #getCameraPosition()} returns an intermediate location of the camera in flight.
- *
- * @param update The change that should be applied to the camera.
- * @param callback The callback to invoke from the main thread when the animation stops. If the
- * animation completes normally, onFinish() is called; otherwise, onCancel() is
- * called. Do not update or animate the camera from within onCancel().
- * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
- */
- @UiThread
- public final void animateCamera(CameraUpdate update, MapboxMap.CancelableCallback callback) {
- animateCamera(update, MapboxConstants.ANIMATION_DURATION, callback);
- }
-
- /**
- * Animate the camera to a new location defined within {@link CameraUpdate} using a transition
- * animation that evokes powered flight. The animation will last a specified amount of time
- * given in milliseconds. During the animation, a call to {@link #getCameraPosition()} returns
- * an intermediate location of the camera in flight.
- *
- * @param update The change that should be applied to the camera.
- * @param durationMs The duration of the animation in milliseconds. This must be strictly
- * positive, otherwise an IllegalArgumentException will be thrown.
- * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
- */
- @UiThread
- public final void animateCamera(CameraUpdate update, int durationMs) {
- animateCamera(update, durationMs, null);
- }
-
- /**
- * Animate the camera to a new location defined within {@link CameraUpdate} using a transition
- * animation that evokes powered flight. The animation will last a specified amount of time
- * given in milliseconds. A callback can be used to be notified when animating the camera stops.
- * During the animation, a call to {@link #getCameraPosition()} returns an intermediate location
- * of the camera in flight.
- *
- * @param update The change that should be applied to the camera.
- * @param durationMs The duration of the animation in milliseconds. This must be strictly
- * positive, otherwise an IllegalArgumentException will be thrown.
- * @param callback An optional callback to be notified from the main thread when the animation
- * stops. If the animation stops due to its natural completion, the callback
- * will be notified with onFinish(). If the animation stops due to interruption
- * by a later camera movement or a user gesture, onCancel() will be called.
- * Do not update or animate the camera from within onCancel(). If a callback
- * isn't required, leave it as null.
- * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
- */
- @UiThread
- public final void animateCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) {
- cameraPosition = update.getCameraPosition(this);
- mapView.resetTrackingModesIfRequired(cameraPosition);
- mapView.flyTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt,
- cameraPosition.zoom, new CancelableCallback() {
- @Override
- public void onCancel() {
- if (callback != null) {
- callback.onCancel();
- }
- invalidateCameraPosition();
- }
-
- @Override
- public void onFinish() {
- if (onCameraChangeListener != null) {
- onCameraChangeListener.onCameraChange(cameraPosition);
- }
-
- if (callback != null) {
- callback.onFinish();
- }
- invalidateCameraPosition();
- }
- });
- }
-
- /**
- * Converts milliseconds to nanoseconds
- *
- * @param durationMs The time in milliseconds
- * @return time in nanoseconds
- */
- private long getDurationNano(long durationMs) {
- return durationMs > 0 ? TimeUnit.NANOSECONDS.convert(durationMs, TimeUnit.MILLISECONDS) : 0;
- }
-
- /**
- * Invalidates the current camera position by reconstructing it from mbgl
- */
- private void invalidateCameraPosition() {
- if(invalidCameraPosition) {
- invalidCameraPosition = false;
-
- CameraPosition cameraPosition = mapView.invalidateCameraPosition();
- if (cameraPosition != null) {
- this.cameraPosition = cameraPosition;
- }
-
- if (onCameraChangeListener != null) {
- onCameraChangeListener.onCameraChange(this.cameraPosition);
- }
- }
- }
-
- //
- // Reset North
- //
-
- /**
- * Resets the map view to face north.
- */
- public void resetNorth() {
- mapView.resetNorth();
- }
+public final class MapboxMap {
+
+ private final NativeMapView nativeMapView;
+
+ private final UiSettings uiSettings;
+ private final TrackingSettings trackingSettings;
+ private final Projection projection;
+ private final Transform transform;
+ private final AnnotationManager annotationManager;
+ private final MyLocationViewSettings myLocationViewSettings;
+
+ private final OnRegisterTouchListener onRegisterTouchListener;
+
+ private MapboxMap.OnFpsChangedListener onFpsChangedListener;
+
+ MapboxMap(NativeMapView map, Transform transform, UiSettings ui, TrackingSettings tracking,
+ MyLocationViewSettings myLocationView, Projection projection, OnRegisterTouchListener listener,
+ AnnotationManager annotations) {
+ this.nativeMapView = map;
+ this.uiSettings = ui;
+ this.trackingSettings = tracking;
+ this.projection = projection;
+ this.myLocationViewSettings = myLocationView;
+ this.annotationManager = annotations.bind(this);
+ this.transform = transform;
+ this.onRegisterTouchListener = listener;
+ }
+
+ void initialise(@NonNull Context context, @NonNull MapboxMapOptions options) {
+ transform.initialise(this, options);
+ uiSettings.initialise(context, options);
+ myLocationViewSettings.initialise(options);
+ trackingSettings.initialise(options);
+
+ // Map configuration
+ setDebugActive(options.getDebugActive());
+ setApiBaseUrl(options);
+ setStyleUrl(options);
+ }
+
+ void onStart() {
+ nativeMapView.update();
+ trackingSettings.onStart();
+ if (TextUtils.isEmpty(nativeMapView.getStyleUrl())) {
+ // if user hasn't loaded a Style yet
+ nativeMapView.setStyleUrl(Style.MAPBOX_STREETS);
+ }
+ }
+
+ void onStop() {
+ trackingSettings.onStop();
+ }
+
+ void onSaveInstanceState(Bundle outState) {
+ outState.putParcelable(MapboxConstants.STATE_CAMERA_POSITION, transform.getCameraPosition());
+ outState.putBoolean(MapboxConstants.STATE_DEBUG_ACTIVE, nativeMapView.getDebug());
+ outState.putString(MapboxConstants.STATE_STYLE_URL, nativeMapView.getStyleUrl());
+ trackingSettings.onSaveInstanceState(outState);
+ uiSettings.onSaveInstanceState(outState);
+ }
+
+ void onRestoreInstanceState(Bundle savedInstanceState) {
+ final CameraPosition cameraPosition = savedInstanceState.getParcelable(MapboxConstants.STATE_CAMERA_POSITION);
+ if (cameraPosition != null) {
+ moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder(cameraPosition).build()));
+ }
+
+ uiSettings.onRestoreInstanceState(savedInstanceState);
+ trackingSettings.onRestoreInstanceState(savedInstanceState);
+ nativeMapView.setDebug(savedInstanceState.getBoolean(MapboxConstants.STATE_DEBUG_ACTIVE));
+
+ final String styleUrl = savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL);
+ if (!TextUtils.isEmpty(styleUrl)) {
+ nativeMapView.setStyleUrl(savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL));
+ }
+ }
+
+ /**
+ * Called before the OnMapReadyCallback is invoked.
+ */
+ void onPreMapReady() {
+ annotationManager.reloadMarkers();
+ annotationManager.adjustTopOffsetPixels(this);
+ }
+
+ /**
+ * Called when the OnMapReadyCallback has finished executing.
+ * <p>
+ * Invalidation of the camera position is required to update the added components in
+ * OnMapReadyCallback with the correct transformation.
+ * </p>
+ */
+ void onPostMapReady() {
+ invalidateCameraPosition();
+ }
+
+ /**
+ * Called when the user
+ */
+ void onUpdate() {
+ CameraPosition cameraPosition = transform.invalidateCameraPosition();
+ uiSettings.update(cameraPosition);
+ // FIXME introduce update method with camera position
+ trackingSettings.update();
+ annotationManager.update();
+ }
+
+ // Style
+
+ @Nullable
+ @UiThread
+ public Layer getLayer(@NonNull String layerId) {
+ return nativeMapView.getLayer(layerId);
+ }
+
+ /**
+ * Tries to cast the Layer to T, returns null if it's another type.
+ *
+ * @param layerId the layer id used to look up a layer
+ * @param <T> the generic attribute of a Layer
+ * @return the casted Layer, null if another type
+ */
+ @Nullable
+ @UiThread
+ public <T extends Layer> T getLayerAs(@NonNull String layerId) {
+ try {
+ //noinspection unchecked
+ return (T) nativeMapView.getLayer(layerId);
+ } catch (ClassCastException exception) {
+ Timber.e(String.format("Layer: %s is a different type: %s", layerId, exception));
+ return null;
+ }
+ }
+
+ /**
+ * Adds the layer to the map. The layer must be newly created and not added to the map before
+ *
+ * @param layer the layer to add
+ */
+ @UiThread
+ public void addLayer(@NonNull Layer layer) {
+ addLayer(layer, null);
+ }
+
+ /**
+ * Adds the layer to the map. The layer must be newly created and not added to the map before
+ *
+ * @param layer the layer to add
+ * @param before the layer id to add this layer before
+ */
+ @UiThread
+ public void addLayer(@NonNull Layer layer, String before) {
+ nativeMapView.addLayer(layer, before);
+ }
+
+ /**
+ * Removes the layer. Any references to the layer become invalid and should not be used anymore
+ *
+ * @param layerId the layer to remove
+ * @throws NoSuchLayerException the exception thrown when layer with layerId doesn't exist
+ */
+ @UiThread
+ public void removeLayer(@NonNull String layerId) throws NoSuchLayerException {
+ nativeMapView.removeLayer(layerId);
+ }
+
+ /**
+ * Removes the layer. The reference is re-usable after this and can be re-added
+ *
+ * @param layer the layer to remove
+ * @throws NoSuchLayerException the exeption thrown when the layer doesn't exist
+ */
+ @UiThread
+ public void removeLayer(@NonNull Layer layer) throws NoSuchLayerException {
+ nativeMapView.removeLayer(layer);
+ }
+
+ @Nullable
+ @UiThread
+ public Source getSource(@NonNull String sourceId) {
+ return nativeMapView.getSource(sourceId);
+ }
+
+ /**
+ * Tries to cast the Source to T, returns null if it's another type.
+ *
+ * @param sourceId the id used to look up a layer
+ * @param <T> the generic type of a Source
+ * @return the casted Source, null if another type
+ */
+ @Nullable
+ @UiThread
+ public <T extends Source> T getSourceAs(@NonNull String sourceId) {
+ try {
+ //noinspection unchecked
+ return (T) nativeMapView.getSource(sourceId);
+ } catch (ClassCastException exception) {
+ Timber.e(String.format("Source: %s is a different type: %s", sourceId, exception));
+ return null;
+ }
+ }
+
+ /**
+ * Adds the source to the map. The source must be newly created and not added to the map before
+ *
+ * @param source the source to add
+ */
+ @UiThread
+ public void addSource(@NonNull Source source) {
+ nativeMapView.addSource(source);
+ }
+
+ /**
+ * Removes the source. Any references to the source become invalid and should not be used anymore
+ *
+ * @param sourceId the source to remove
+ * @throws NoSuchSourceException the exception thrown when the source with sourceId doesn't exist
+ */
+ @UiThread
+ public void removeSource(@NonNull String sourceId) throws NoSuchSourceException {
+ nativeMapView.removeSource(sourceId);
+ }
+
+ /**
+ * Removes the source, preserving the reverence for re-use
+ *
+ * @param source the source to remove
+ * @throws NoSuchSourceException the exception thrown when the source with sourceId doesn't exist
+ */
+ @UiThread
+ public void removeSource(@NonNull Source source) throws NoSuchSourceException {
+ nativeMapView.removeSource(source);
+ }
+
+ /**
+ * Adds an image to be used in the map's style
+ *
+ * @param name the name of the image
+ * @param image the pre-multiplied Bitmap
+ */
+ @UiThread
+ public void addImage(@NonNull String name, @NonNull Bitmap image) {
+ nativeMapView.addImage(name, image);
+ }
+
+ /**
+ * Removes an image from the map's style
+ *
+ * @param name the name of the image to remove
+ */
+ @UiThread
+ public void removeImage(String name) {
+ nativeMapView.removeImage(name);
+ }
+
+ //
+ // MinZoom
+ //
+
+ /**
+ * <p>
+ * Sets the minimum zoom level the map can be displayed at.
+ * </p>
+ *
+ * @param minZoom The new minimum zoom level.
+ */
+ @UiThread
+ public void setMinZoomPreference(
+ @FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) {
+ transform.setMinZoom(minZoom);
+ }
+
+ /**
+ * <p>
+ * Gets the maximum zoom level the map can be displayed at.
+ * </p>
+ *
+ * @return The minimum zoom level.
+ */
+ @UiThread
+ public double getMinZoomLevel() {
+ return transform.getMinZoom();
+ }
+
+ //
+ // MaxZoom
+ //
+
+ /**
+ * <p>
+ * Sets the maximum zoom level the map can be displayed at.
+ * </p>
+ *
+ * @param maxZoom The new maximum zoom level.
+ */
+ @UiThread
+ public void setMaxZoomPreference(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM,
+ to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) {
+ transform.setMaxZoom(maxZoom);
+ }
+
+ /**
+ * <p>
+ * Gets the maximum zoom level the map can be displayed at.
+ * </p>
+ *
+ * @return The maximum zoom level.
+ */
+ @UiThread
+ public double getMaxZoomLevel() {
+ return transform.getMaxZoom();
+ }
+
+ //
+ // UiSettings
+ //
+
+ /**
+ * Gets the user interface settings for the map.
+ *
+ * @return the UiSettings associated with this map
+ */
+ public UiSettings getUiSettings() {
+ return uiSettings;
+ }
+
+ //
+ // TrackingSettings
+ //
+
+ /**
+ * Gets the tracking interface settings for the map.
+ *
+ * @return the TrackingSettings asssociated with this map
+ */
+ public TrackingSettings getTrackingSettings() {
+ return trackingSettings;
+ }
+
+ //
+ // MyLocationViewSettings
+ //
+
+ /**
+ * Gets the settings of the user location for the map.
+ *
+ * @return the MyLocationViewSettings associated with this map
+ */
+ public MyLocationViewSettings getMyLocationViewSettings() {
+ return myLocationViewSettings;
+ }
+
+ //
+ // Projection
+ //
+
+ /**
+ * Get the Projection object that you can use to convert between screen coordinates and latitude/longitude
+ * coordinates.
+ *
+ * @return the Projection associated with this map
+ */
+ public Projection getProjection() {
+ return projection;
+ }
+
+ //
+ // Camera API
+ //
+
+ /**
+ * Cancels ongoing animations.
+ * <p>
+ * This invokes the {@link CancelableCallback} for ongoing camera updates.
+ * </p>
+ */
+ public void cancelTransitions() {
+ transform.cancelTransitions();
+ }
+
+ /**
+ * Gets the current position of the camera.
+ * The CameraPosition returned is a snapshot of the current position, and will not automatically update when the
+ * camera moves.
+ *
+ * @return The current position of the Camera.
+ */
+ public final CameraPosition getCameraPosition() {
+ return transform.getCameraPosition();
+ }
+
+ /**
+ * Repositions the camera according to the cameraPosition.
+ * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position.
+ * See CameraUpdateFactory for a set of updates.
+ *
+ * @param cameraPosition the camera position to set
+ */
+ public void setCameraPosition(@NonNull CameraPosition cameraPosition) {
+ moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), null);
+ }
+
+ /**
+ * Repositions the camera according to the instructions defined in the update.
+ * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position.
+ * See CameraUpdateFactory for a set of updates.
+ *
+ * @param update The change that should be applied to the camera.
+ */
+ @UiThread
+ public final void moveCamera(CameraUpdate update) {
+ moveCamera(update, null);
+ // MapChange.REGION_DID_CHANGE_ANIMATED is not called for `jumpTo`
+ // invalidate camera position to provide OnCameraChange event.
+ invalidateCameraPosition();
+ }
+
+ /**
+ * Repositions the camera according to the instructions defined in the update.
+ * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position.
+ * See CameraUpdateFactory for a set of updates.
+ *
+ * @param update The change that should be applied to the camera
+ * @param callback the callback to be invoked when an animation finishes or is canceled
+ */
+ @UiThread
+ public final void moveCamera(final CameraUpdate update, final MapboxMap.CancelableCallback callback) {
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+ transform.moveCamera(MapboxMap.this, update, callback);
+ }
+ });
+ }
+
+ /**
+ * Gradually move the camera by the default duration, zoom will not be affected unless specified
+ * within {@link CameraUpdate}. If {@link #getCameraPosition()} is called during the animation,
+ * it will return the current location of the camera in flight.
+ *
+ * @param update The change that should be applied to the camera.
+ * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
+ */
+ @UiThread
+ public final void easeCamera(CameraUpdate update) {
+ easeCamera(update, MapboxConstants.ANIMATION_DURATION);
+ }
+
+ /**
+ * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected
+ * unless specified within {@link CameraUpdate}. If {@link #getCameraPosition()} is called
+ * during the animation, it will return the current location of the camera in flight.
+ *
+ * @param update The change that should be applied to the camera.
+ * @param durationMs The duration of the animation in milliseconds. This must be strictly
+ * positive, otherwise an IllegalArgumentException will be thrown.
+ * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
+ */
+ @UiThread
+ public final void easeCamera(CameraUpdate update, int durationMs) {
+ easeCamera(update, durationMs, null);
+ }
+
+ /**
+ * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected
+ * unless specified within {@link CameraUpdate}. A callback can be used to be notified when
+ * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it
+ * will return the current location of the camera in flight.
+ * <p>
+ * Note that this will cancel location tracking mode if enabled.
+ * </p>
+ *
+ * @param update The change that should be applied to the camera.
+ * @param durationMs The duration of the animation in milliseconds. This must be strictly
+ * positive, otherwise an IllegalArgumentException will be thrown.
+ * @param callback An optional callback to be notified from the main thread when the animation
+ * stops. If the animation stops due to its natural completion, the callback
+ * will be notified with onFinish(). If the animation stops due to interruption
+ * by a later camera movement or a user gesture, onCancel() will be called.
+ * Do not update or ease the camera from within onCancel().
+ * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
+ */
+ @UiThread
+ public final void easeCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) {
+ easeCamera(update, durationMs, true, callback);
+ }
+
+ /**
+ * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected
+ * unless specified within {@link CameraUpdate}. A callback can be used to be notified when
+ * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it
+ * will return the current location of the camera in flight.
+ * <p>
+ * Note that this will cancel location tracking mode if enabled.
+ * </p>
+ *
+ * @param update The change that should be applied to the camera.
+ * @param durationMs The duration of the animation in milliseconds. This must be strictly
+ * positive, otherwise an IllegalArgumentException will be thrown.
+ * @param easingInterpolator True for easing interpolator, false for linear.
+ */
+ @UiThread
+ public final void easeCamera(CameraUpdate update, int durationMs, boolean easingInterpolator) {
+ easeCamera(update, durationMs, easingInterpolator, null);
+ }
+
+ /**
+ * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected
+ * unless specified within {@link CameraUpdate}. A callback can be used to be notified when
+ * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it
+ * will return the current location of the camera in flight.
+ * <p>
+ * Note that this will cancel location tracking mode if enabled.
+ * </p>
+ *
+ * @param update The change that should be applied to the camera.
+ * @param durationMs The duration of the animation in milliseconds. This must be strictly
+ * positive, otherwise an IllegalArgumentException will be thrown.
+ * @param easingInterpolator True for easing interpolator, false for linear.
+ * @param callback An optional callback to be notified from the main thread when the animation
+ * stops. If the animation stops due to its natural completion, the callback
+ * will be notified with onFinish(). If the animation stops due to interruption
+ * by a later camera movement or a user gesture, onCancel() will be called.
+ * Do not update or ease the camera from within onCancel().
+ */
+ @UiThread
+ public final void easeCamera(
+ CameraUpdate update, int durationMs, boolean easingInterpolator, final MapboxMap.CancelableCallback callback) {
+ // dismiss tracking, moving camera is equal to a gesture
+ easeCamera(update, durationMs, easingInterpolator, true, callback);
+ }
+
+ /**
+ * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected
+ * unless specified within {@link CameraUpdate}. A callback can be used to be notified when
+ * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it
+ * will return the current location of the camera in flight.
+ * <p>
+ * Note that this will cancel location tracking mode if enabled.
+ * </p>
+ *
+ * @param update The change that should be applied to the camera.
+ * @param durationMs The duration of the animation in milliseconds. This must be strictly
+ * positive, otherwise an IllegalArgumentException will be thrown.
+ * @param resetTrackingMode True to reset tracking modes if required, false to ignore
+ * @param easingInterpolator True for easing interpolator, false for linear.
+ * @param callback An optional callback to be notified from the main thread when the animation
+ * stops. If the animation stops due to its natural completion, the callback
+ * will be notified with onFinish(). If the animation stops due to interruption
+ * by a later camera movement or a user gesture, onCancel() will be called.
+ * Do not update or ease the camera from within onCancel().
+ */
+ @UiThread
+ public final void easeCamera(final CameraUpdate update, final int durationMs, final boolean easingInterpolator,
+ final boolean resetTrackingMode, final MapboxMap.CancelableCallback callback) {
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+ transform.easeCamera(MapboxMap.this, update, durationMs, easingInterpolator, resetTrackingMode, callback);
+ }
+ });
+ }
+
+ /**
+ * Animate the camera to a new location defined within {@link CameraUpdate} using a transition
+ * animation that evokes powered flight. The animation will last the default amount of time.
+ * During the animation, a call to {@link #getCameraPosition()} returns an intermediate location
+ * of the camera in flight.
+ *
+ * @param update The change that should be applied to the camera.
+ * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
+ */
+ @UiThread
+ public final void animateCamera(CameraUpdate update) {
+ animateCamera(update, MapboxConstants.ANIMATION_DURATION, null);
+ }
+
+ /**
+ * Animate the camera to a new location defined within {@link CameraUpdate} using a transition
+ * animation that evokes powered flight. The animation will last the default amount of time. A
+ * callback can be used to be notified when animating the camera stops. During the animation, a
+ * call to {@link #getCameraPosition()} returns an intermediate location of the camera in flight.
+ *
+ * @param update The change that should be applied to the camera.
+ * @param callback The callback to invoke from the main thread when the animation stops. If the
+ * animation completes normally, onFinish() is called; otherwise, onCancel() is
+ * called. Do not update or animate the camera from within onCancel().
+ * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
+ */
+ @UiThread
+ public final void animateCamera(CameraUpdate update, MapboxMap.CancelableCallback callback) {
+ animateCamera(update, MapboxConstants.ANIMATION_DURATION, callback);
+ }
+
+ /**
+ * Animate the camera to a new location defined within {@link CameraUpdate} using a transition
+ * animation that evokes powered flight. The animation will last a specified amount of time
+ * given in milliseconds. During the animation, a call to {@link #getCameraPosition()} returns
+ * an intermediate location of the camera in flight.
+ *
+ * @param update The change that should be applied to the camera.
+ * @param durationMs The duration of the animation in milliseconds. This must be strictly
+ * positive, otherwise an IllegalArgumentException will be thrown.
+ * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
+ */
+ @UiThread
+ public final void animateCamera(CameraUpdate update, int durationMs) {
+ animateCamera(update, durationMs, null);
+ }
+
+ /**
+ * Animate the camera to a new location defined within {@link CameraUpdate} using a transition
+ * animation that evokes powered flight. The animation will last a specified amount of time
+ * given in milliseconds. A callback can be used to be notified when animating the camera stops.
+ * During the animation, a call to {@link #getCameraPosition()} returns an intermediate location
+ * of the camera in flight.
+ *
+ * @param update The change that should be applied to the camera.
+ * @param durationMs The duration of the animation in milliseconds. This must be strictly
+ * positive, otherwise an IllegalArgumentException will be thrown.
+ * @param callback An optional callback to be notified from the main thread when the animation
+ * stops. If the animation stops due to its natural completion, the callback
+ * will be notified with onFinish(). If the animation stops due to interruption
+ * by a later camera movement or a user gesture, onCancel() will be called.
+ * Do not update or animate the camera from within onCancel(). If a callback
+ * isn't required, leave it as null.
+ * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
+ */
+ @UiThread
+ public final void animateCamera(final CameraUpdate update, final int durationMs,
+ final MapboxMap.CancelableCallback callback) {
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+ transform.animateCamera(MapboxMap.this, update, durationMs, callback);
+ }
+ });
+ }
+
+ /**
+ * Invalidates the current camera position by reconstructing it from mbgl
+ */
+ void invalidateCameraPosition() {
+ CameraPosition cameraPosition = transform.invalidateCameraPosition();
+ if (cameraPosition != null) {
+ transform.updateCameraPosition(cameraPosition);
+ }
+ }
+
+ //
+ // Reset North
+ //
+
+ /**
+ * Resets the map view to face north.
+ */
+ public void resetNorth() {
+ transform.resetNorth();
+ }
+
+ //
+ // Debug
+ //
+
+ /**
+ * Returns whether the map debug information is currently shown.
+ *
+ * @return If true, map debug information is currently shown.
+ */
+ @UiThread
+ public boolean isDebugActive() {
+ return nativeMapView.getDebug();
+ }
+
+ /**
+ * <p>
+ * Changes whether the map debug information is shown.
+ * </p>
+ * The default value is false.
+ *
+ * @param debugActive If true, map debug information is shown.
+ */
+ @UiThread
+ public void setDebugActive(boolean debugActive) {
+ nativeMapView.setDebug(debugActive);
+ }
+
+ /**
+ * <p>
+ * Cycles through the map debug options.
+ * </p>
+ * The value of isDebugActive reflects whether there are
+ * any map debug options enabled or disabled.
+ *
+ * @see #isDebugActive()
+ */
+ @UiThread
+ public void cycleDebugOptions() {
+ nativeMapView.cycleDebugOptions();
+ }
+
+ //
+ // API endpoint config
+ //
+
+ private void setApiBaseUrl(@NonNull MapboxMapOptions options) {
+ String apiBaseUrl = options.getApiBaseUrl();
+ if (!TextUtils.isEmpty(apiBaseUrl)) {
+ nativeMapView.setApiBaseUrl(apiBaseUrl);
+ }
+ }
+
+ //
+ // Styling
+ //
+
+ /**
+ * <p>
+ * Loads a new map style from the specified URL.
+ * </p>
+ * {@code url} can take the following forms:
+ * <ul>
+ * <li>{@code Style.*}: load one of the bundled styles in {@link Style}.</li>
+ * <li>{@code mapbox://styles/<user>/<style>}:
+ * retrieves the style from a <a href="https://www.mapbox.com/account/">Mapbox account.</a>
+ * {@code user} is your username. {@code style} is the ID of your custom
+ * style created in <a href="https://www.mapbox.com/studio">Mapbox Studio</a>.</li>
+ * <li>{@code http://...} or {@code https://...}:
+ * retrieves the style over the Internet from any web server.</li>
+ * <li>{@code asset://...}:
+ * reads the style from the APK {@code assets/} directory.
+ * This is used to load a style bundled with your app.</li>
+ * <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li>
+ * </ul>
+ * <p>
+ * This method is asynchronous and will return immediately before the style finishes loading.
+ * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event.
+ * </p>
+ * If the style fails to load or an invalid style URL is set, the map view will become blank.
+ * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be
+ * sent.
+ *
+ * @param url The URL of the map style
+ * @see Style
+ */
+ @UiThread
+ public void setStyleUrl(@NonNull String url) {
+ nativeMapView.setStyleUrl(url);
+ }
+
+ /**
+ * <p>
+ * Loads a new map style from the specified bundled style.
+ * </p>
+ * <p>
+ * This method is asynchronous and will return immediately before the style finishes loading.
+ * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event.
+ * </p>
+ * If the style fails to load or an invalid style URL is set, the map view will become blank.
+ * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be
+ * sent.
+ *
+ * @param style The bundled style. Accepts one of the values from {@link Style}.
+ * @see Style
+ * @deprecated use {@link #setStyleUrl(String)} instead with versioned url methods from {@link Style}
+ */
+ @UiThread
+ @Deprecated
+ public void setStyle(@Style.StyleUrl String style) {
+ setStyleUrl(style);
+ }
+
+ /**
+ * Loads a new map style from MapboxMapOptions if available.
+ *
+ * @param options the object containing the style url
+ */
+ private void setStyleUrl(@NonNull MapboxMapOptions options) {
+ String style = options.getStyle();
+ if (!TextUtils.isEmpty(style)) {
+ // stopgap for https://github.com/mapbox/mapbox-gl-native/issues/6242
+ if (TextUtils.isEmpty(nativeMapView.getAccessToken())) {
+ nativeMapView.setAccessToken(Mapbox.getAccessToken());
+ }
+ setStyleUrl(style);
+ }
+ }
+
+ /**
+ * <p>
+ * Returns the map style currently displayed in the map view.
+ * </p>
+ * If the default style is currently displayed, a URL will be returned instead of null.
+ *
+ * @return The URL of the map style.
+ */
+ @UiThread
+ @NonNull
+ public String getStyleUrl() {
+ return nativeMapView.getStyleUrl();
+ }
+
+ //
+ // Annotations
+ //
+
+ /**
+ * <p>
+ * Adds a marker to this map.
+ * </p>
+ * The marker's icon is rendered on the map at the location {@code Marker.position}.
+ * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet.
+ *
+ * @param markerOptions A marker options object that defines how to render the marker.
+ * @return The {@code Marker} that was added to the map.
+ */
+ @UiThread
+ @NonNull
+ public Marker addMarker(@NonNull MarkerOptions markerOptions) {
+ return annotationManager.addMarker(markerOptions, this);
+ }
+
+ /**
+ * <p>
+ * Adds a marker to this map.
+ * </p>
+ * The marker's icon is rendered on the map at the location {@code Marker.position}.
+ * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet.
+ *
+ * @param markerOptions A marker options object that defines how to render the marker.
+ * @return The {@code Marker} that was added to the map.
+ */
+ @UiThread
+ @NonNull
+ public Marker addMarker(@NonNull BaseMarkerOptions markerOptions) {
+ return annotationManager.addMarker(markerOptions, this);
+ }
+
+ /**
+ * <p>
+ * Adds a marker to this map.
+ * </p>
+ * The marker's icon is rendered on the map at the location {@code Marker.position}.
+ * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet.
+ *
+ * @param markerOptions A marker options object that defines how to render the marker.
+ * @return The {@code Marker} that was added to the map.
+ */
+ @UiThread
+ @NonNull
+ public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions) {
+ return annotationManager.addMarker(markerOptions, this, null);
+ }
+
+
+ /**
+ * <p>
+ * Adds a marker to this map.
+ * </p>
+ * The marker's icon is rendered on the map at the location {@code Marker.position}.
+ * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet.
+ *
+ * @param markerOptions A marker options object that defines how to render the marker.
+ * @param onMarkerViewAddedListener Callback invoked when the View has been added to the map.
+ * @return The {@code Marker} that was added to the map.
+ */
+ @UiThread
+ @NonNull
+ public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions,
+ final MarkerViewManager.OnMarkerViewAddedListener onMarkerViewAddedListener) {
+ return annotationManager.addMarker(markerOptions, this, onMarkerViewAddedListener);
+ }
+
+ /**
+ * FIXME javadoc
+ */
+ @UiThread
+ @NonNull
+ public List<MarkerView> addMarkerViews(@NonNull List<? extends
+ BaseMarkerViewOptions> markerViewOptions) {
+ return annotationManager.addMarkerViews(markerViewOptions, this);
+ }
+
+ /**
+ * FIXME javadoc
+ */
+ @UiThread
+ @NonNull
+ public List<MarkerView> getMarkerViewsInRect(@NonNull RectF rect) {
+ return annotationManager.getMarkerViewsInRect(rect);
+ }
+
+ /**
+ * <p>
+ * Adds multiple markers to this map.
+ * </p>
+ * The marker's icon is rendered on the map at the location {@code Marker.position}.
+ * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet.
+ *
+ * @param markerOptionsList A list of marker options objects that defines how to render the markers.
+ * @return A list of the {@code Marker}s that were added to the map.
+ */
+ @UiThread
+ @NonNull
+ public List<Marker> addMarkers(@NonNull List<? extends
+ BaseMarkerOptions> markerOptionsList) {
+ return annotationManager.addMarkers(markerOptionsList, this);
+ }
+
+ /**
+ * <p>
+ * Updates a marker on this map. Does nothing if the marker isn't already added.
+ * </p>
+ *
+ * @param updatedMarker An updated marker object.
+ */
+ @UiThread
+ public void updateMarker(@NonNull Marker updatedMarker) {
+ annotationManager.updateMarker(updatedMarker, this);
+ }
+
+ /**
+ * Adds a polyline to this map.
+ *
+ * @param polylineOptions A polyline options object that defines how to render the polyline.
+ * @return The {@code Polyine} that was added to the map.
+ */
+ @UiThread
+ @NonNull
+ public Polyline addPolyline(@NonNull PolylineOptions polylineOptions) {
+ return annotationManager.addPolyline(polylineOptions, this);
+ }
+
+ /**
+ * Adds multiple polylines to this map.
+ *
+ * @param polylineOptionsList A list of polyline options objects that defines how to render the polylines.
+ * @return A list of the {@code Polyline}s that were added to the map.
+ */
+ @UiThread
+ @NonNull
+ public List<Polyline> addPolylines(@NonNull List<PolylineOptions> polylineOptionsList) {
+ return annotationManager.addPolylines(polylineOptionsList, this);
+ }
+
+ /**
+ * Update a polyline on this map.
+ *
+ * @param polyline An updated polyline object.
+ */
+ @UiThread
+ public void updatePolyline(Polyline polyline) {
+ annotationManager.updatePolyline(polyline);
+ }
+
+ /**
+ * Adds a polygon to this map.
+ *
+ * @param polygonOptions A polygon options object that defines how to render the polygon.
+ * @return The {@code Polygon} that was added to the map.
+ */
+ @UiThread
+ @NonNull
+ public Polygon addPolygon(@NonNull PolygonOptions polygonOptions) {
+ return annotationManager.addPolygon(polygonOptions, this);
+ }
+
+ /**
+ * Adds multiple polygons to this map.
+ *
+ * @param polygonOptionsList A list of polygon options objects that defines how to render the polygons.
+ * @return A list of the {@code Polygon}s that were added to the map.
+ */
+ @UiThread
+ @NonNull
+ public List<Polygon> addPolygons(@NonNull List<PolygonOptions> polygonOptionsList) {
+ return annotationManager.addPolygons(polygonOptionsList, this);
+ }
+
+
+ /**
+ * Update a polygon on this map.
+ *
+ * @param polygon An updated polygon object.
+ */
+ @UiThread
+ public void updatePolygon(Polygon polygon) {
+ annotationManager.updatePolygon(polygon);
+ }
+
+ /**
+ * <p>
+ * Convenience method for removing a Marker from the map.
+ * </p>
+ * Calls removeAnnotation() internally
+ *
+ * @param marker Marker to remove
+ */
+ @UiThread
+ public void removeMarker(@NonNull Marker marker) {
+ annotationManager.removeAnnotation(marker);
+ }
+
+ /**
+ * <p>
+ * Convenience method for removing a Polyline from the map.
+ * </p>
+ * Calls removeAnnotation() internally
+ *
+ * @param polyline Polyline to remove
+ */
+ @UiThread
+ public void removePolyline(@NonNull Polyline polyline) {
+ annotationManager.removeAnnotation(polyline);
+ }
+
+ /**
+ * <p>
+ * Convenience method for removing a Polygon from the map.
+ * </p>
+ * Calls removeAnnotation() internally
+ *
+ * @param polygon Polygon to remove
+ */
+ @UiThread
+ public void removePolygon(@NonNull Polygon polygon) {
+ annotationManager.removeAnnotation(polygon);
+ }
+
+ /**
+ * Removes an annotation from the map.
+ *
+ * @param annotation The annotation object to remove.
+ */
+ @UiThread
+ public void removeAnnotation(@NonNull Annotation annotation) {
+ annotationManager.removeAnnotation(annotation);
+ }
+
+ /**
+ * Removes an annotation from the map
+ *
+ * @param id The identifier associated to the annotation to be removed
+ */
+ @UiThread
+ public void removeAnnotation(long id) {
+ annotationManager.removeAnnotation(id);
+ }
+
+ /**
+ * Removes multiple annotations from the map.
+ *
+ * @param annotationList A list of annotation objects to remove.
+ */
+ @UiThread
+ public void removeAnnotations(@NonNull List<? extends Annotation> annotationList) {
+ annotationManager.removeAnnotations(annotationList);
+ }
+
+ /**
+ * Removes all annotations from the map.
+ */
+ @UiThread
+ public void removeAnnotations() {
+ annotationManager.removeAnnotations();
+ }
+
+ /**
+ * Removes all markers, polylines, polygons, overlays, etc from the map.
+ */
+ @UiThread
+ public void clear() {
+ annotationManager.removeAnnotations();
+ }
+
+ /**
+ * Return a annotation based on its id.
+ *
+ * @param id the id used to look up an annotation
+ * @return An annotation with a matched id, null is returned if no match was found
+ */
+ @Nullable
+ public Annotation getAnnotation(long id) {
+ return annotationManager.getAnnotation(id);
+ }
+
+ /**
+ * Returns a list of all the annotations on the map.
+ *
+ * @return A list of all the annotation objects. The returned object is a copy so modifying this
+ * list will not update the map
+ */
+ @NonNull
+ public List<Annotation> getAnnotations() {
+ return annotationManager.getAnnotations();
+ }
+
+ /**
+ * Returns a list of all the markers on the map.
+ *
+ * @return A list of all the markers objects. The returned object is a copy so modifying this
+ * list will not update the map.
+ */
+ @NonNull
+ public List<Marker> getMarkers() {
+ return annotationManager.getMarkers();
+ }
+
+ /**
+ * Returns a list of all the polygons on the map.
+ *
+ * @return A list of all the polygon objects. The returned object is a copy so modifying this
+ * list will not update the map.
+ */
+ @NonNull
+ public List<Polygon> getPolygons() {
+ return annotationManager.getPolygons();
+ }
+
+ /**
+ * Returns a list of all the polylines on the map.
+ *
+ * @return A list of all the polylines objects. The returned object is a copy so modifying this
+ * list will not update the map.
+ */
+ @NonNull
+ public List<Polyline> getPolylines() {
+ return annotationManager.getPolylines();
+ }
+
+ /**
+ * Sets a callback that's invoked when the user clicks on a marker.
+ *
+ * @param listener The callback that's invoked when the user clicks on a marker.
+ * To unset the callback, use null.
+ */
+ @UiThread
+ public void setOnMarkerClickListener(@Nullable OnMarkerClickListener listener) {
+ annotationManager.setOnMarkerClickListener(listener);
+ }
+
+ /**
+ * <p>
+ * Selects a marker. The selected marker will have it's info window opened.
+ * Any other open info windows will be closed unless isAllowConcurrentMultipleOpenInfoWindows()
+ * is true.
+ * </p>
+ * Selecting an already selected marker will have no effect.
+ *
+ * @param marker The marker to select.
+ */
+ @UiThread
+ public void selectMarker(@NonNull Marker marker) {
+ if (marker == null) {
+ Timber.w("marker was null, so just returning");
+ return;
+ }
+ annotationManager.selectMarker(marker);
+ }
+
+ /**
+ * Deselects any currently selected marker. All markers will have it's info window closed.
+ */
+ @UiThread
+ public void deselectMarkers() {
+ annotationManager.deselectMarkers();
+ }
+
+ /**
+ * Deselects a currently selected marker. The selected marker will have it's info window closed.
+ *
+ * @param marker the marker to deselect
+ */
+ @UiThread
+ public void deselectMarker(@NonNull Marker marker) {
+ annotationManager.deselectMarker(marker);
+ }
+
+ /**
+ * Gets the currently selected marker.
+ *
+ * @return The currently selected marker.
+ */
+ @UiThread
+ public List<Marker> getSelectedMarkers() {
+ return annotationManager.getSelectedMarkers();
+ }
+
+ /**
+ * Get the MarkerViewManager associated to the MapView.
+ *
+ * @return the associated MarkerViewManager
+ */
+ public MarkerViewManager getMarkerViewManager() {
+ return annotationManager.getMarkerViewManager();
+ }
+
+ //
+ // InfoWindow
+ //
+
+ /**
+ * <p>
+ * Sets a custom renderer for the contents of info window.
+ * </p>
+ * When set your callback is invoked when an info window is about to be shown. By returning
+ * a custom {@link View}, the default info window will be replaced.
+ *
+ * @param infoWindowAdapter The callback to be invoked when an info window will be shown.
+ * To unset the callback, use null.
+ */
+ @UiThread
+ public void setInfoWindowAdapter(@Nullable InfoWindowAdapter infoWindowAdapter) {
+ annotationManager.getInfoWindowManager().setInfoWindowAdapter(infoWindowAdapter);
+ }
+
+ /**
+ * Gets the callback to be invoked when an info window will be shown.
+ *
+ * @return The callback to be invoked when an info window will be shown.
+ */
+ @UiThread
+ @Nullable
+ public InfoWindowAdapter getInfoWindowAdapter() {
+ return annotationManager.getInfoWindowManager().getInfoWindowAdapter();
+ }
+
+ /**
+ * Changes whether the map allows concurrent multiple infowindows to be shown.
+ *
+ * @param allow If true, map allows concurrent multiple infowindows to be shown.
+ */
+ @UiThread
+ public void setAllowConcurrentMultipleOpenInfoWindows(boolean allow) {
+ annotationManager.getInfoWindowManager().setAllowConcurrentMultipleOpenInfoWindows(allow);
+ }
+
+ /**
+ * Returns whether the map allows concurrent multiple infowindows to be shown.
+ *
+ * @return If true, map allows concurrent multiple infowindows to be shown.
+ */
+ @UiThread
+ public boolean isAllowConcurrentMultipleOpenInfoWindows() {
+ return annotationManager.getInfoWindowManager().isAllowConcurrentMultipleOpenInfoWindows();
+ }
+
+ //
+ // Padding
+ //
+
+ /**
+ * <p>
+ * Sets the distance from the edges of the map view’s frame to the edges of the map
+ * view’s logical viewport.
+ * </p>
+ * <p>
+ * When the value of this property is equal to {0,0,0,0}, viewport
+ * properties such as `centerCoordinate` assume a viewport that matches the map
+ * view’s frame. Otherwise, those properties are inset, excluding part of the
+ * frame from the viewport. For instance, if the only the top edge is inset, the
+ * map center is effectively shifted downward.
+ * </p>
+ *
+ * @param left The left margin in pixels.
+ * @param top The top margin in pixels.
+ * @param right The right margin in pixels.
+ * @param bottom The bottom margin in pixels.
+ */
+ public void setPadding(int left, int top, int right, int bottom) {
+ projection.setContentPadding(new int[] {left, top, right, bottom}, myLocationViewSettings.getPadding());
+ uiSettings.invalidate();
+ }
+
+ /**
+ * Returns the current configured content padding on map view.
+ *
+ * @return An array with length 4 in the LTRB order.
+ */
+ public int[] getPadding() {
+ return projection.getContentPadding();
+ }
+
+ //
+ // Map events
+ //
+
+ /**
+ * Sets a callback that's invoked on every change in camera position.
+ *
+ * @param listener The callback that's invoked on every camera change position.
+ * To unset the callback, use null.
+ */
+ @UiThread
+ public void setOnCameraChangeListener(@Nullable OnCameraChangeListener listener) {
+ transform.setOnCameraChangeListener(listener);
+ }
+
+ /**
+ * Sets a callback that's invoked on every frame rendered to the map view.
+ *
+ * @param listener The callback that's invoked on every frame rendered to the map view.
+ * To unset the callback, use null.
+ */
+ @UiThread
+ public void setOnFpsChangedListener(@Nullable OnFpsChangedListener listener) {
+ onFpsChangedListener = listener;
+ }
+
+ // used by MapView
+ OnFpsChangedListener getOnFpsChangedListener() {
+ return onFpsChangedListener;
+ }
+
+ /**
+ * Sets a callback that's invoked when the map is scrolled.
+ *
+ * @param listener The callback that's invoked when the map is scrolled.
+ * To unset the callback, use null.
+ */
+ @UiThread
+ public void setOnScrollListener(@Nullable OnScrollListener listener) {
+ onRegisterTouchListener.onRegisterScrollListener(listener);
+ }
+
+ /**
+ * Sets a callback that's invoked when the map is flinged.
+ *
+ * @param listener The callback that's invoked when the map is flinged.
+ * To unset the callback, use null.
+ */
+ @UiThread
+ public void setOnFlingListener(@Nullable OnFlingListener listener) {
+ onRegisterTouchListener.onRegisterFlingListener(listener);
+ }
+
+ /**
+ * Sets a callback that's invoked when the user clicks on the map view.
+ *
+ * @param listener The callback that's invoked when the user clicks on the map view.
+ * To unset the callback, use null.
+ */
+ @UiThread
+ public void setOnMapClickListener(@Nullable OnMapClickListener listener) {
+ onRegisterTouchListener.onRegisterMapClickListener(listener);
+ }
+
+ /**
+ * Sets a callback that's invoked when the user long clicks on the map view.
+ *
+ * @param listener The callback that's invoked when the user long clicks on the map view.
+ * To unset the callback, use null.
+ */
+ @UiThread
+ public void setOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
+ onRegisterTouchListener.onRegisterMapLongClickListener(listener);
+ }
+
+ /**
+ * Sets a callback that's invoked when the user clicks on an info window.
+ *
+ * @param listener The callback that's invoked when the user clicks on an info window.
+ * To unset the callback, use null.
+ */
+ @UiThread
+ public void setOnInfoWindowClickListener(@Nullable OnInfoWindowClickListener listener) {
+ annotationManager.getInfoWindowManager().setOnInfoWindowClickListener(listener);
+ }
+
+ /**
+ * Return the InfoWindow click listener
+ *
+ * @return Current active InfoWindow Click Listener
+ */
+ @UiThread
+ public OnInfoWindowClickListener getOnInfoWindowClickListener() {
+ return annotationManager.getInfoWindowManager().getOnInfoWindowClickListener();
+ }
+
+ /**
+ * Sets a callback that's invoked when a marker's info window is long pressed.
+ *
+ * @param listener The callback that's invoked when a marker's info window is long pressed. To unset the callback,
+ * use null.
+ */
+ @UiThread
+ public void setOnInfoWindowLongClickListener(@Nullable OnInfoWindowLongClickListener
+ listener) {
+ annotationManager.getInfoWindowManager().setOnInfoWindowLongClickListener(listener);
+ }
+
+ /**
+ * Return the InfoWindow long click listener
+ *
+ * @return Current active InfoWindow long Click Listener
+ */
+ public OnInfoWindowLongClickListener getOnInfoWindowLongClickListener() {
+ return annotationManager.getInfoWindowManager().getOnInfoWindowLongClickListener();
+ }
+
+ public void setOnInfoWindowCloseListener(@Nullable OnInfoWindowCloseListener listener) {
+ annotationManager.getInfoWindowManager().setOnInfoWindowCloseListener(listener);
+ }
+
+ /**
+ * Return the InfoWindow close listener
+ *
+ * @return Current active InfoWindow Close Listener
+ */
+ @UiThread
+ public OnInfoWindowCloseListener getOnInfoWindowCloseListener() {
+ return annotationManager.getInfoWindowManager().getOnInfoWindowCloseListener();
+ }
+
+ //
+ // User location
+ //
+
+ /**
+ * Returns the status of the my-location layer.
+ *
+ * @return True if the my-location layer is enabled, false otherwise.
+ */
+ @UiThread
+ public boolean isMyLocationEnabled() {
+ return trackingSettings.isMyLocationEnabled();
+ }
+
+ /**
+ * <p>
+ * Enables or disables the my-location layer.
+ * While enabled, the my-location layer continuously draws an indication of a user's current
+ * location and bearing.
+ * </p>
+ * In order to use the my-location layer feature you need to request permission for either
+ * android.Manifest.permission#ACCESS_COARSE_LOCATION or android.Manifest.permission#ACCESS_FINE_LOCATION.
+ *
+ * @param enabled True to enable; false to disable.
+ */
+ @UiThread
+ public void setMyLocationEnabled(boolean enabled) {
+ trackingSettings.setMyLocationEnabled(enabled);
+ }
+
+ /**
+ * Returns the currently displayed user location, or null if there is no location data available.
+ *
+ * @return The currently displayed user location.
+ */
+ @UiThread
+ @Nullable
+ public Location getMyLocation() {
+ return trackingSettings.getMyLocation();
+ }
+
+ /**
+ * Sets a callback that's invoked when the the My Location view
+ * (which signifies the user's location) changes location.
+ *
+ * @param listener The callback that's invoked when the user clicks on a marker.
+ * To unset the callback, use null.
+ */
+ @UiThread
+ public void setOnMyLocationChangeListener(@Nullable MapboxMap.OnMyLocationChangeListener
+ listener) {
+ trackingSettings.setOnMyLocationChangeListener(listener);
+ }
+
+ /**
+ * Sets a callback that's invoked when the location tracking mode changes.
+ *
+ * @param listener The callback that's invoked when the location tracking mode changes.
+ * To unset the callback, use null.
+ */
+ @UiThread
+ public void setOnMyLocationTrackingModeChangeListener(
+ @Nullable MapboxMap.OnMyLocationTrackingModeChangeListener listener) {
+ trackingSettings.setOnMyLocationTrackingModeChangeListener(listener);
+ }
+
+ /**
+ * Sets a callback that's invoked when the bearing tracking mode changes.
+ *
+ * @param listener The callback that's invoked when the bearing tracking mode changes.
+ * To unset the callback, use null.
+ */
+ @UiThread
+ public void setOnMyBearingTrackingModeChangeListener(@Nullable OnMyBearingTrackingModeChangeListener listener) {
+ trackingSettings.setOnMyBearingTrackingModeChangeListener(listener);
+ }
+
+ //
+ // Invalidate
+ //
+
+ /**
+ * Takes a snapshot of the map.
+ *
+ * @param callback Callback method invoked when the snapshot is taken.
+ * @param bitmap A pre-allocated bitmap.
+ */
+ @UiThread
+ public void snapshot(@NonNull SnapshotReadyCallback callback, @Nullable final Bitmap bitmap) {
+ nativeMapView.addSnapshotCallback(callback, bitmap);
+ }
+
+ /**
+ * Takes a snapshot of the map.
+ *
+ * @param callback Callback method invoked when the snapshot is taken.
+ */
+ @UiThread
+ public void snapshot(@NonNull SnapshotReadyCallback callback) {
+ snapshot(callback, null);
+ }
+
+ /**
+ * Queries the map for rendered features
+ *
+ * @param coordinates the point to query
+ * @param layerIds optionally - only query these layers
+ * @return the list of feature
+ */
+ @UiThread
+ @NonNull
+ public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates, @Nullable String...
+ layerIds) {
+ return nativeMapView.queryRenderedFeatures(coordinates, layerIds);
+ }
+
+ /**
+ * Queries the map for rendered features
+ *
+ * @param coordinates the box to query
+ * @param layerIds optionally - only query these layers
+ * @return the list of feature
+ */
+ @UiThread
+ @NonNull
+ public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates, @Nullable String...
+ layerIds) {
+ return nativeMapView.queryRenderedFeatures(coordinates, layerIds);
+ }
+
+ //
+ // Interfaces
+ //
+
+ /**
+ * Interface definition for a callback to be invoked when the map is flinged.
+ *
+ * @see MapboxMap#setOnFlingListener(OnFlingListener)
+ */
+ public interface OnFlingListener {
+ /**
+ * Called when the map is flinged.
+ */
+ void onFling();
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when the map is scrolled.
+ *
+ * @see MapboxMap#setOnScrollListener(OnScrollListener)
+ */
+ public interface OnScrollListener {
+ /**
+ * Called when the map is scrolled.
+ */
+ void onScroll();
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when the camera changes position.
+ */
+ public interface OnCameraChangeListener {
+ /**
+ * Called after the camera position has changed. During an animation,
+ * this listener may not be notified of intermediate camera positions.
+ * It is always called for the final position in the animation.
+ *
+ * @param position The CameraPosition at the end of the last camera change.
+ */
+ void onCameraChange(CameraPosition position);
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when a frame is rendered to the map view.
+ *
+ * @see MapboxMap#setOnFpsChangedListener(OnFpsChangedListener)
+ */
+ public interface OnFpsChangedListener {
+ /**
+ * Called for every frame rendered to the map view.
+ *
+ * @param fps The average number of frames rendered over the last second.
+ */
+ void onFpsChanged(double fps);
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when a user registers an listener that is
+ * related to touch and click events.
+ */
+ interface OnRegisterTouchListener {
+ void onRegisterMapClickListener(OnMapClickListener listener);
+
+ void onRegisterMapLongClickListener(OnMapLongClickListener listener);
+
+ void onRegisterScrollListener(OnScrollListener listener);
- //
- // Debug
- //
+ void onRegisterFlingListener(OnFlingListener listener);
+ }
+ /**
+ * Interface definition for a callback to be invoked when the user clicks on the map view.
+ *
+ * @see MapboxMap#setOnMapClickListener(OnMapClickListener)
+ */
+ public interface OnMapClickListener {
/**
- * Returns whether the map debug information is currently shown.
+ * Called when the user clicks on the map view.
*
- * @return If true, map debug information is currently shown.
+ * @param point The projected map coordinate the user clicked on.
*/
- @UiThread
- public boolean isDebugActive() {
- return mapView.isDebugActive();
- }
+ void onMapClick(@NonNull LatLng point);
+ }
+ /**
+ * Interface definition for a callback to be invoked when the user long clicks on the map view.
+ *
+ * @see MapboxMap#setOnMapLongClickListener(OnMapLongClickListener)
+ */
+ public interface OnMapLongClickListener {
/**
- * <p>
- * Changes whether the map debug information is shown.
- * </p>
- * The default value is false.
+ * Called when the user long clicks on the map view.
*
- * @param debugActive If true, map debug information is shown.
+ * @param point The projected map coordinate the user long clicked on.
*/
- @UiThread
- public void setDebugActive(boolean debugActive) {
- mapView.setDebugActive(debugActive);
- }
+ void onMapLongClick(@NonNull LatLng point);
+ }
+ /**
+ * Interface definition for a callback to be invoked when the user clicks on a marker.
+ *
+ * @see MapboxMap#setOnMarkerClickListener(OnMarkerClickListener)
+ */
+ public interface OnMarkerClickListener {
/**
- * <p>
- * Cycles through the map debug options.
- * </p>
- * The value of {@link MapView#isDebugActive()} reflects whether there are
- * any map debug options enabled or disabled.
+ * Called when the user clicks on a marker.
*
- * @see MapView#isDebugActive()
+ * @param marker The marker the user clicked on.
+ * @return If true the listener has consumed the event and the info window will not be shown.
*/
- @UiThread
- public void cycleDebugOptions() {
- mapView.cycleDebugOptions();
- }
-
- //
- // Styling
- //
+ boolean onMarkerClick(@NonNull Marker marker);
+ }
+ /**
+ * Interface definition for a callback to be invoked when the user clicks on an info window.
+ *
+ * @see MapboxMap#setOnInfoWindowClickListener(OnInfoWindowClickListener)
+ */
+ public interface OnInfoWindowClickListener {
/**
- * <p>
- * Loads a new map style from the specified URL.
- * </p>
- * {@code url} can take the following forms:
- * <ul>
- * <li>{@code Style.*}: load one of the bundled styles in {@link Style}.</li>
- * <li>{@code mapbox://styles/<user>/<style>}:
- * retrieves the style from a <a href="https://www.mapbox.com/account/">Mapbox account.</a>
- * {@code user} is your username. {@code style} is the ID of your custom
- * style created in <a href="https://www.mapbox.com/studio">Mapbox Studio</a>.</li>
- * <li>{@code http://...} or {@code https://...}:
- * retrieves the style over the Internet from any web server.</li>
- * <li>{@code asset://...}:
- * reads the style from the APK {@code assets/} directory.
- * This is used to load a style bundled with your app.</li>
- * <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li>
- * </ul>
- * <p>
- * This method is asynchronous and will return immediately before the style finishes loading.
- * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event.
- * </p>
- * If the style fails to load or an invalid style URL is set, the map view will become blank.
- * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be
- * sent.
+ * Called when the user clicks on an info window.
*
- * @param url The URL of the map style
- * @see Style
+ * @param marker The marker of the info window the user clicked on.
+ * @return If true the listener has consumed the event and the info window will not be closed.
*/
- @UiThread
- public void setStyleUrl(@NonNull String url) {
- mapView.setStyleUrl(url);
- }
+ boolean onInfoWindowClick(@NonNull Marker marker);
+ }
- /**
- * <p>
- * Loads a new map style from the specified bundled style.
- * </p>
- * <p>
- * This method is asynchronous and will return immediately before the style finishes loading.
- * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event.
- * </p>
- * If the style fails to load or an invalid style URL is set, the map view will become blank.
- * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be
- * sent.
- *
- * @param style The bundled style. Accepts one of the values from {@link Style}.
- * @see Style
- * @deprecated use {@link #setStyleUrl(String)} instead with versioned url methods from {@link Style}
- */
- @UiThread
- @Deprecated
- public void setStyle(@Style.StyleUrl String style) {
- setStyleUrl(style);
- }
+ /**
+ * Interface definition for a callback to be invoked when the user long presses on a marker's info window.
+ *
+ * @see MapboxMap#setOnInfoWindowClickListener(OnInfoWindowClickListener)
+ */
+ public interface OnInfoWindowLongClickListener {
/**
- * <p>
- * Returns the map style currently displayed in the map view.
- * </p>
- * If the default style is currently displayed, a URL will be returned instead of null.
+ * Called when the user makes a long-press gesture on the marker's info window.
*
- * @return The URL of the map style.
+ * @param marker The marker were the info window is attached to
*/
- @UiThread
- @NonNull
- public String getStyleUrl() {
- return mapView.getStyleUrl();
- }
+ void onInfoWindowLongClick(Marker marker);
+ }
- //
- // Access token
- //
+ /**
+ * Interface definition for a callback to be invoked when a marker's info window is closed.
+ *
+ * @see MapboxMap#setOnInfoWindowCloseListener(OnInfoWindowCloseListener)
+ */
+ public interface OnInfoWindowCloseListener {
/**
- * <p>
- * DEPRECATED @see MapboxAccountManager#start(String)
- * </p>
- * <p>
- * Sets the current Mapbox access token used to load map styles and tiles.
- * </p>
+ * Called when the marker's info window is closed.
*
- * @param accessToken Your public Mapbox access token.
- * @see MapView#setAccessToken(String)
- * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)}
+ * @param marker The marker of the info window that was closed.
*/
- @Deprecated
- @UiThread
- public void setAccessToken(@NonNull String accessToken) {
- mapView.setAccessToken(accessToken);
- }
+ void onInfoWindowClose(Marker marker);
+ }
+ /**
+ * Interface definition for a callback to be invoked when an info window will be shown.
+ *
+ * @see MapboxMap#setInfoWindowAdapter(InfoWindowAdapter)
+ */
+ public interface InfoWindowAdapter {
/**
- * <p>
- * DEPRECATED @see MapboxAccountManager#getAccessToken()
- * </p>
- * <p>
- * Returns the current Mapbox access token used to load map styles and tiles.
- * </p>
+ * Called when an info window will be shown as a result of a marker click.
*
- * @return The current Mapbox access token.
- * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#getAccessToken()}
+ * @param marker The marker the user clicked on.
+ * @return View to be shown as a info window. If null is returned the default
+ * info window will be shown.
*/
- @Deprecated
- @UiThread
@Nullable
- public String getAccessToken() {
- return mapView.getAccessToken();
- }
+ View getInfoWindow(@NonNull Marker marker);
+ }
- //
- // Annotations
- //
+ /**
+ * Interface definition for a callback to be invoked when an MarkerView will be shown.
+ *
+ * @param <U> the instance type of MarkerView
+ */
+ public abstract static class MarkerViewAdapter<U extends MarkerView> {
- void setTilt(double tilt) {
- mapView.setTilt(tilt);
- }
+ private Context context;
+ private final Class<U> persistentClass;
+ private final Pools.SimplePool<View> viewReusePool;
/**
- * <p>
- * Adds a marker to this map.
- * </p>
- * The marker's icon is rendered on the map at the location {@code Marker.position}.
- * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet.
+ * Create an instance of MarkerViewAdapter.
*
- * @param markerOptions A marker options object that defines how to render the marker.
- * @return The {@code Marker} that was added to the map.
+ * @param context the context associated to a MapView
*/
- @UiThread
- @NonNull
- public Marker addMarker(@NonNull MarkerOptions markerOptions) {
- return addMarker((BaseMarkerOptions) markerOptions);
+ @SuppressWarnings("unchecked")
+ public MarkerViewAdapter(Context context) {
+ this.context = context;
+ persistentClass = (Class<U>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
+ viewReusePool = new Pools.SimplePool<>(10000);
}
/**
- * <p>
- * Adds a marker to this map.
- * </p>
- * The marker's icon is rendered on the map at the location {@code Marker.position}.
- * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet.
- *
- * @param markerOptions A marker options object that defines how to render the marker.
- * @return The {@code Marker} that was added to the map.
- */
- @UiThread
- @NonNull
- public Marker addMarker(@NonNull BaseMarkerOptions markerOptions) {
- Marker marker = prepareMarker(markerOptions);
- long id = mapView.addMarker(marker);
- marker.setMapboxMap(this);
- marker.setId(id);
- annotations.put(id, marker);
- return marker;
- }
-
- /**
- * <p>
- * Adds a marker to this map.
- * </p>
- * The marker's icon is rendered on the map at the location {@code Marker.position}.
- * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet.
- *
- * @param markerOptions A marker options object that defines how to render the marker.
- * @return The {@code Marker} that was added to the map.
- */
- @UiThread
- @NonNull
- public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions) {
- MarkerView marker = prepareViewMarker(markerOptions);
- marker.setMapboxMap(this);
- long id = mapView.addMarker(marker);
- marker.setId(id);
- annotations.put(id, marker);
- markerViewManager.invalidateViewMarkersInVisibleRegion();
- return marker;
- }
-
- @UiThread
- @NonNull
- public List<MarkerView> addMarkerViews(@NonNull List<? extends BaseMarkerViewOptions> markerViewOptions) {
- List<MarkerView> markers = new ArrayList<>();
- for (BaseMarkerViewOptions markerViewOption : markerViewOptions) {
- MarkerView marker = prepareViewMarker(markerViewOption);
- marker.setMapboxMap(this);
- long id = mapView.addMarker(marker);
- marker.setId(id);
- annotations.put(id, marker);
- markers.add(marker);
- }
- markerViewManager.invalidateViewMarkersInVisibleRegion();
- return markers;
- }
-
- /**
- * <p>
- * Adds multiple markers to this map.
- * </p>
- * The marker's icon is rendered on the map at the location {@code Marker.position}.
- * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet.
- *
- * @param markerOptionsList A list of marker options objects that defines how to render the markers.
- * @return A list of the {@code Marker}s that were added to the map.
- */
- @UiThread
- @NonNull
- public List<Marker> addMarkers(@NonNull List<? extends BaseMarkerOptions> markerOptionsList) {
- 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);
- }
-
- if (markers.size() > 0) {
- long[] ids = mapView.addMarkers(markers);
-
- // if unittests or markers are correctly added to map
- if (ids == null || ids.length == markers.size()) {
- long id = 0;
- Marker m;
- for (int i = 0; i < markers.size(); i++) {
- m = markers.get(i);
- m.setMapboxMap(this);
- if (ids != null) {
- id = ids[i];
- } else {
- //unit test
- id++;
- }
- m.setId(id);
- annotations.put(id, m);
- }
- }
- }
- }
- return markers;
- }
-
- /**
- * <p>
- * Updates a marker on this map. Does nothing if the marker is already added.
- * </p>
- *
- * @param updatedMarker An updated marker object.
- */
- @UiThread
- public void updateMarker(@NonNull Marker updatedMarker) {
- mapView.updateMarker(updatedMarker);
-
- int index = annotations.indexOfKey(updatedMarker.getId());
- if (index > -1) {
- annotations.setValueAt(index, updatedMarker);
- }
- }
-
- /**
- * Update a polygon on this map.
- *
- * @param polygon An updated polygon object.
- */
- @UiThread
- public void updatePolygon(Polygon polygon) {
- mapView.updatePolygon(polygon);
-
- int index = annotations.indexOfKey(polygon.getId());
- if (index > -1) {
- annotations.setValueAt(index, polygon);
- }
- }
-
- /**
- * Update a polyline on this map.
- *
- * @param polyline An updated polyline object.
- */
- @UiThread
- public void updatePolyline(Polyline polyline) {
- mapView.updatePolyline(polyline);
-
- int index = annotations.indexOfKey(polyline.getId());
- if (index > -1) {
- annotations.setValueAt(index, polyline);
- }
- }
-
- /**
- * Adds a polyline to this map.
- *
- * @param polylineOptions A polyline options object that defines how to render the polyline.
- * @return The {@code Polyine} that was added to the map.
- */
- @UiThread
- @NonNull
- public Polyline addPolyline(@NonNull PolylineOptions polylineOptions) {
- Polyline polyline = polylineOptions.getPolyline();
- if (!polyline.getPoints().isEmpty()) {
- long id = mapView.addPolyline(polyline);
- polyline.setMapboxMap(this);
- polyline.setId(id);
- annotations.put(id, polyline);
- }
- return polyline;
- }
-
- /**
- * Adds multiple polylines to this map.
- *
- * @param polylineOptionsList A list of polyline options objects that defines how to render the polylines.
- * @return A list of the {@code Polyline}s that were added to the map.
- */
- @UiThread
- @NonNull
- public List<Polyline> addPolylines(@NonNull List<PolylineOptions> polylineOptionsList) {
- 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 = mapView.addPolylines(polylines);
-
- // if unit tests or polylines are correctly added to map
- if (ids == null || ids.length == polylines.size()) {
- long id = 0;
- Polyline p;
-
- for (int i = 0; i < polylines.size(); i++) {
- p = polylines.get(i);
- p.setMapboxMap(this);
- if (ids != null) {
- id = ids[i];
- } else {
- // unit test
- id++;
- }
- p.setId(id);
- annotations.put(id, p);
- }
- }
- }
- return polylines;
- }
-
- /**
- * Adds a polygon to this map.
- *
- * @param polygonOptions A polygon options object that defines how to render the polygon.
- * @return The {@code Polygon} that was added to the map.
- */
- @UiThread
- @NonNull
- public Polygon addPolygon(@NonNull PolygonOptions polygonOptions) {
- Polygon polygon = polygonOptions.getPolygon();
- if (!polygon.getPoints().isEmpty()) {
- long id = mapView.addPolygon(polygon);
- polygon.setId(id);
- polygon.setMapboxMap(this);
- annotations.put(id, polygon);
- }
- return polygon;
- }
-
- /**
- * Adds multiple polygons to this map.
- *
- * @param polygonOptionsList A list of polygon options objects that defines how to render the polygons.
- * @return A list of the {@code Polygon}s that were added to the map.
- */
- @UiThread
- @NonNull
- public List<Polygon> addPolygons(@NonNull List<PolygonOptions> polygonOptionsList) {
- 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 = mapView.addPolygons(polygons);
-
- // if unit tests or polygons correctly added to map
- if (ids == null || ids.length == polygons.size()) {
- long id = 0;
- for (int i = 0; i < polygons.size(); i++) {
- polygon = polygons.get(i);
- polygon.setMapboxMap(this);
- if (ids != null) {
- id = ids[i];
- } else {
- // unit test
- id++;
- }
- polygon.setId(id);
- annotations.put(id, polygon);
- }
- }
- }
- return polygons;
- }
-
- /**
- * <p>
- * Convenience method for removing a Marker from the map.
- * </p>
- * Calls removeAnnotation() internally
- *
- * @param marker Marker to remove
- */
- @UiThread
- public void removeMarker(@NonNull Marker marker) {
- removeAnnotation(marker);
- }
-
- /**
- * <p>
- * Convenience method for removing a Polyline from the map.
- * </p>
- * Calls removeAnnotation() internally
- *
- * @param polyline Polyline to remove
- */
- @UiThread
- public void removePolyline(@NonNull Polyline polyline) {
- removeAnnotation(polyline);
- }
-
- /**
- * <p>
- * Convenience method for removing a Polygon from the map.
- * </p>
- * Calls removeAnnotation() internally
+ * Called when an MarkerView will be added to the MapView.
*
- * @param polygon Polygon to remove
- */
- @UiThread
- public void removePolygon(@NonNull Polygon polygon) {
- removeAnnotation(polygon);
- }
-
- /**
- * Removes an annotation from the map.
- *
- * @param annotation The annotation object to remove.
- */
- @UiThread
- public void removeAnnotation(@NonNull Annotation annotation) {
- if (annotation instanceof Marker) {
- Marker marker = (Marker) annotation;
- marker.hideInfoWindow();
- if (marker instanceof MarkerView) {
- markerViewManager.removeMarkerView((MarkerView) marker);
- }
- }
- long id = annotation.getId();
- mapView.removeAnnotation(id);
- annotations.remove(id);
- }
-
- /**
- * Removes an annotation from the map
- *
- * @param id The identifier associated to the annotation to be removed
- */
- @UiThread
- public void removeAnnotation(long id) {
- mapView.removeAnnotation(id);
- annotations.remove(id);
- }
-
- /**
- * Removes multiple annotations from the map.
- *
- * @param annotationList A list of annotation objects to remove.
- */
- @UiThread
- public void removeAnnotations(@NonNull List<? extends 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();
- if (marker instanceof MarkerView) {
- markerViewManager.removeMarkerView((MarkerView) marker);
- }
- }
- ids[i] = annotationList.get(i).getId();
- }
- mapView.removeAnnotations(ids);
- for (long id : ids) {
- annotations.remove(id);
- }
- }
-
- /**
- * Removes all annotations from the map.
- */
- @UiThread
- public void removeAnnotations() {
- Annotation annotation;
- int count = annotations.size();
- long[] ids = new long[count];
- for (int i = 0; i < count; 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);
- }
- }
- }
- mapView.removeAnnotations(ids);
- annotations.clear();
- }
-
- /**
- * Removes all markers, polylines, polygons, overlays, etc from the map.
- */
- @UiThread
- public void clear() {
- removeAnnotations();
- }
-
- /**
- * Return a annotation based on its id.
- *
- * @param id the id used to look up an annotation
- * @return An annotation with a matched id, null is returned if no match was found
+ * @param marker the model representing the MarkerView
+ * @param convertView the reusable view
+ * @param parent the parent ViewGroup of the convertview
+ * @return the View that is adapted to the contents of MarkerView
*/
@Nullable
- public Annotation getAnnotation(long id) {
- return annotations.get(id);
- }
-
- /**
- * Returns a list of all the annotations on the map.
- *
- * @return A list of all the annotation objects. The returned object is a copy so modifying this
- * list will not update the map
- */
- @NonNull
- public List<Annotation> getAnnotations() {
- 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;
- }
-
- /**
- * Returns a list of all the markers on the map.
- *
- * @return A list of all the markers objects. The returned object is a copy so modifying this
- * list will not update the map.
- */
- @NonNull
- public 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);
- }
- }
- return markers;
- }
-
- /**
- * Returns a list of all the polygons on the map.
- *
- * @return A list of all the polygon objects. The returned object is a copy so modifying this
- * list will not update the map.
- */
- @NonNull
- public 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;
- }
-
- /**
- * Returns a list of all the polylines on the map.
- *
- * @return A list of all the polylines objects. The returned object is a copy so modifying this
- * list will not update the map.
- */
- @NonNull
- public 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;
- }
+ public abstract View getView(@NonNull U marker, @Nullable View convertView, @NonNull ViewGroup parent);
/**
+ * Called when an MarkerView is removed from the MapView or the View object is going to be reused.
* <p>
- * Selects a marker. The selected marker will have it's info window opened.
- * Any other open info windows will be closed unless isAllowConcurrentMultipleOpenInfoWindows()
- * is true.
+ * This method should be used to reset an animated view back to it's original state for view reuse.
* </p>
- * Selecting an already selected marker will have no effect.
- *
- * @param marker The marker to select.
- */
- @UiThread
- public void selectMarker(@NonNull Marker marker) {
- if (marker == null) {
- Log.w(MapboxConstants.TAG, "marker was null, so just returning");
- return;
- }
-
- if (selectedMarkers.contains(marker)) {
- return;
- }
-
- // Need to deselect any currently selected annotation first
- if (!isAllowConcurrentMultipleOpenInfoWindows()) {
- deselectMarkers();
- }
-
- boolean handledDefaultClick = false;
- if (onMarkerClickListener != null) {
- // end developer has provided a custom click listener
- handledDefaultClick = onMarkerClickListener.onMarkerClick(marker);
- }
-
- if (!handledDefaultClick) {
- if (marker instanceof MarkerView) {
- markerViewManager.select((MarkerView) marker, false);
- markerViewManager.ensureInfoWindowOffset((MarkerView) marker);
- }
-
- if (isInfoWindowValidForMarker(marker) || getInfoWindowAdapter() != null) {
- infoWindows.add(marker.showInfoWindow(this, mapView));
- }
- }
-
- selectedMarkers.add(marker);
- }
-
- /**
- * Deselects any currently selected marker. All markers will have it's info window closed.
- */
- @UiThread
- public void deselectMarkers() {
- if (selectedMarkers.isEmpty()) {
- return;
- }
-
- for (Marker marker : selectedMarkers) {
- if (marker.isInfoWindowShown()) {
- marker.hideInfoWindow();
- }
-
- if (marker instanceof MarkerView) {
- markerViewManager.deselect((MarkerView) marker, false);
- }
- }
-
- // Removes all selected markers from the list
- selectedMarkers.clear();
- }
-
- /**
- * Deselects a currently selected marker. The selected marker will have it's info window closed.
- *
- * @param marker the marker to deselect
- */
- @UiThread
- public void deselectMarker(@NonNull Marker marker) {
- if (!selectedMarkers.contains(marker)) {
- return;
- }
-
- if (marker.isInfoWindowShown()) {
- marker.hideInfoWindow();
- }
-
- if (marker instanceof MarkerView) {
- markerViewManager.deselect((MarkerView) marker, false);
- }
-
- selectedMarkers.remove(marker);
- }
-
- /**
- * Gets the currently selected marker.
- *
- * @return The currently selected marker.
- */
- @UiThread
- public List<Marker> getSelectedMarkers() {
- return selectedMarkers;
- }
-
- private Marker prepareMarker(BaseMarkerOptions markerOptions) {
- Marker marker = markerOptions.getMarker();
- Icon icon = mapView.loadIconForMarker(marker);
- marker.setTopOffsetPixels(mapView.getTopOffsetPixelsForIcon(icon));
- return marker;
- }
-
- private MarkerView prepareViewMarker(BaseMarkerViewOptions markerViewOptions) {
- MarkerView marker = markerViewOptions.getMarker();
- mapView.loadIconForMarkerView(marker);
- return marker;
- }
-
- /**
- * Get the MarkerViewManager associated to the MapView.
- *
- * @return the associated MarkerViewManager
- */
- public MarkerViewManager getMarkerViewManager() {
- return markerViewManager;
- }
-
- //
- // InfoWindow
- //
-
- /**
* <p>
- * Sets a custom renderer for the contents of info window.
+ * Returning true indicates you want to the view reuse to be handled automatically.
+ * Returning false indicates you want to perform an animation and you are required calling
+ * {@link #releaseView(View)} yourself.
* </p>
- * When set your callback is invoked when an info window is about to be shown. By returning
- * a custom {@link View}, the default info window will be replaced.
- *
- * @param infoWindowAdapter The callback to be invoked when an info window will be shown.
- * To unset the callback, use null.
- */
- @UiThread
- public void setInfoWindowAdapter(@Nullable InfoWindowAdapter infoWindowAdapter) {
- this.infoWindowAdapter = infoWindowAdapter;
- }
-
- /**
- * Gets the callback to be invoked when an info window will be shown.
- *
- * @return The callback to be invoked when an info window will be shown.
- */
- @UiThread
- @Nullable
- public InfoWindowAdapter getInfoWindowAdapter() {
- return infoWindowAdapter;
- }
-
- /**
- * Changes whether the map allows concurrent multiple infowindows to be shown.
*
- * @param allow If true, map allows concurrent multiple infowindows to be shown.
+ * @param marker the model representing the MarkerView
+ * @param convertView the reusable view
+ * @return true if you want reuse to occur automatically, false if you want to manage this yourself.
*/
- @UiThread
- public void setAllowConcurrentMultipleOpenInfoWindows(boolean allow) {
- allowConcurrentMultipleInfoWindows = allow;
- }
-
- /**
- * Returns whether the map allows concurrent multiple infowindows to be shown.
- *
- * @return If true, map allows concurrent multiple infowindows to be shown.
- */
- @UiThread
- public boolean isAllowConcurrentMultipleOpenInfoWindows() {
- return allowConcurrentMultipleInfoWindows;
- }
-
- // used by MapView
- List<InfoWindow> getInfoWindows() {
- return infoWindows;
+ public boolean prepareViewForReuse(@NonNull MarkerView marker, @NonNull View convertView) {
+ return true;
}
- private boolean isInfoWindowValidForMarker(@NonNull Marker marker) {
- return !TextUtils.isEmpty(marker.getTitle()) || !TextUtils.isEmpty(marker.getSnippet());
- }
-
- //
- // Padding
- //
-
/**
+ * Called when a MarkerView is selected from the MapView.
* <p>
- * Sets the distance from the edges of the map view’s frame to the edges of the map
- * view’s logical viewport.
- * </p>
- * <p>
- * When the value of this property is equal to {0,0,0,0}, viewport
- * properties such as `centerCoordinate` assume a viewport that matches the map
- * view’s frame. Otherwise, those properties are inset, excluding part of the
- * frame from the viewport. For instance, if the only the top edge is inset, the
- * map center is effectively shifted downward.
+ * Returning true from this method indicates you want to move the MarkerView to the selected state.
+ * Returning false indicates you want to animate the View first an manually select the MarkerView when appropriate.
* </p>
*
- * @param left The left margin in pixels.
- * @param top The top margin in pixels.
- * @param right The right margin in pixels.
- * @param bottom The bottom margin in pixels.
+ * @param marker the model representing the MarkerView
+ * @param convertView the reusable view
+ * @param reselectionFromRecycling indicates if the onSelect callback is the initial selection
+ * callback or that selection occurs due to recreation of selected marker
+ * @return true if you want to select the Marker immediately, false if you want to manage this yourself.
*/
- public void setPadding(int left, int top, int right, int bottom) {
- mapView.setContentPadding(left, top, right, bottom);
- uiSettings.invalidate();
+ public boolean onSelect(@NonNull U marker, @NonNull View convertView, boolean reselectionFromRecycling) {
+ return true;
}
/**
- * Returns the current configured content padding on map view.
+ * Called when a MarkerView is deselected from the MapView.
*
- * @return An array with length 4 in the LTRB order.
+ * @param marker the model representing the MarkerView
+ * @param convertView the reusable view
*/
- public int[] getPadding() {
- return new int[]{mapView.getContentPaddingLeft(),
- mapView.getContentPaddingTop(),
- mapView.getContentPaddingRight(),
- mapView.getContentPaddingBottom()};
+ public void onDeselect(@NonNull U marker, @NonNull View convertView) {
}
- //
- // Map events
- //
-
/**
- * Sets a callback that's invoked on every change in camera position.
+ * Returns the generic type of the used MarkerView.
*
- * @param listener The callback that's invoked on every camera change position.
- * To unset the callback, use null.
+ * @return the generic type
*/
- @UiThread
- public void setOnCameraChangeListener(@Nullable OnCameraChangeListener listener) {
- onCameraChangeListener = listener;
+ public final Class<U> getMarkerClass() {
+ return persistentClass;
}
/**
- * Sets a callback that's invoked on every frame rendered to the map view.
+ * Returns the pool used to store reusable Views.
*
- * @param listener The callback that's invoked on every frame rendered to the map view.
- * To unset the callback, use null.
+ * @return the pool associated to this adapter
*/
- @UiThread
- public void setOnFpsChangedListener(@Nullable OnFpsChangedListener listener) {
- onFpsChangedListener = listener;
- }
-
- // used by MapView
- OnFpsChangedListener getOnFpsChangedListener() {
- return onFpsChangedListener;
+ public final Pools.SimplePool<View> getViewReusePool() {
+ return viewReusePool;
}
/**
- * Sets a callback that's invoked when the map is scrolled.
+ * Returns the context associated to the hosting MapView.
*
- * @param listener The callback that's invoked when the map is scrolled.
- * To unset the callback, use null.
+ * @return the context used
*/
- @UiThread
- public void setOnScrollListener(@Nullable OnScrollListener listener) {
- onScrollListener = listener;
- }
-
- // used by MapView
- OnScrollListener getOnScrollListener() {
- return onScrollListener;
+ public final Context getContext() {
+ return context;
}
/**
- * Sets a callback that's invoked when the map is flinged.
+ * Release a View to the ViewPool.
*
- * @param listener The callback that's invoked when the map is flinged.
- * To unset the callback, use null.
+ * @param view the view to be released
*/
- @UiThread
- public void setOnFlingListener(@Nullable OnFlingListener listener) {
- onFlingListener = listener;
+ public final void releaseView(View view) {
+ view.setVisibility(View.GONE);
+ viewReusePool.release(view);
}
+ }
- // used by MapView
- OnFlingListener getOnFlingListener() {
- return onFlingListener;
- }
+ /**
+ * Interface definition for a callback to be invoked when the user clicks on a MarkerView.
+ */
+ public interface OnMarkerViewClickListener {
/**
- * Sets a callback that's invoked when the user clicks on the map view.
+ * Called when the user clicks on a MarkerView.
*
- * @param listener The callback that's invoked when the user clicks on the map view.
- * To unset the callback, use null.
+ * @param marker the MarkerView associated to the clicked View
+ * @param view the clicked View
+ * @param adapter the adapter used to adapt the MarkerView to the View
+ * @return If true the listener has consumed the event and the info window will not be shown
*/
- @UiThread
- public void setOnMapClickListener(@Nullable OnMapClickListener listener) {
- onMapClickListener = listener;
- }
-
- // used by MapView
- OnMapClickListener getOnMapClickListener() {
- return onMapClickListener;
- }
+ boolean onMarkerClick(@NonNull Marker marker, @NonNull View view, @NonNull MarkerViewAdapter adapter);
+ }
+ /**
+ * Interface definition for a callback to be invoked when the the My Location view changes location.
+ *
+ * @see MapboxMap#setOnMyLocationChangeListener(OnMyLocationChangeListener)
+ */
+ public interface OnMyLocationChangeListener {
/**
- * Sets a callback that's invoked when the user long clicks on the map view.
+ * Called when the location of the My Location view has changed
+ * (be it latitude/longitude, bearing or accuracy).
*
- * @param listener The callback that's invoked when the user long clicks on the map view.
- * To unset the callback, use null.
+ * @param location The current location of the My Location view The type of map change event.
*/
- @UiThread
- public void setOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
- onMapLongClickListener = listener;
- }
+ void onMyLocationChange(@Nullable Location location);
+ }
- // used by MapView
- OnMapLongClickListener getOnMapLongClickListener() {
- return onMapLongClickListener;
- }
+ /**
+ * Interface definition for a callback to be invoked when the the My Location tracking mode changes.
+ *
+ * @see TrackingSettings#setMyLocationTrackingMode(int)
+ */
+ public interface OnMyLocationTrackingModeChangeListener {
/**
- * Sets a callback that's invoked when the user clicks on a marker.
+ * Called when the tracking mode of My Location tracking has changed
*
- * @param listener The callback that's invoked when the user clicks on a marker.
- * To unset the callback, use null.
+ * @param myLocationTrackingMode the current active location tracking mode
*/
- @UiThread
- public void setOnMarkerClickListener(@Nullable OnMarkerClickListener listener) {
- onMarkerClickListener = listener;
- }
+ void onMyLocationTrackingModeChange(@MyLocationTracking.Mode int myLocationTrackingMode);
+ }
- /**
- * Sets a callback that's invoked when the user clicks on an info window.
- *
- * @param listener The callback that's invoked when the user clicks on an info window.
- * To unset the callback, use null.
- */
- @UiThread
- public void setOnInfoWindowClickListener(@Nullable OnInfoWindowClickListener listener) {
- onInfoWindowClickListener = listener;
- }
+ /**
+ * Interface definition for a callback to be invoked when the the My Location tracking mode changes.
+ *
+ * @see TrackingSettings#setMyLocationTrackingMode(int)
+ */
+ public interface OnMyBearingTrackingModeChangeListener {
/**
- * Return the InfoWindow click listener
+ * Called when the tracking mode of My Bearing tracking has changed
*
- * @return Current active InfoWindow Click Listener
+ * @param myBearingTrackingMode the current active bearing tracking mode
*/
- @UiThread
- public OnInfoWindowClickListener getOnInfoWindowClickListener() {
- return onInfoWindowClickListener;
- }
+ void onMyBearingTrackingModeChange(@MyBearingTracking.Mode int myBearingTrackingMode);
+ }
+ /**
+ * Interface definition for a callback to be invoked when a task is complete or cancelled.
+ */
+ public interface CancelableCallback {
/**
- * Sets a callback that's invoked when a marker's info window is long pressed.
- *
- * @param listener The callback that's invoked when a marker's info window is long pressed. To unset the callback,
- * use null.
+ * Invoked when a task is cancelled.
*/
- @UiThread
- public void setOnInfoWindowLongClickListener(@Nullable OnInfoWindowLongClickListener listener) {
- onInfoWindowLongClickListener = listener;
- }
+ void onCancel();
/**
- * Return the InfoWindow long click listener
- *
- * @return Current active InfoWindow long Click Listener
+ * Invoked when a task is complete.
*/
- public OnInfoWindowLongClickListener getOnInfoWindowLongClickListener() {
- return onInfoWindowLongClickListener;
- }
-
- public void setOnInfoWindowCloseListener(@Nullable OnInfoWindowCloseListener listener) {
- onInfoWindowCloseListener = listener;
- }
+ void onFinish();
+ }
+ /**
+ * Interface definition for a callback to be invoked when the snapshot has been taken.
+ */
+ public interface SnapshotReadyCallback {
/**
- * Return the InfoWindow close listener
+ * Invoked when the snapshot has been taken.
*
- * @return Current active InfoWindow Close Listener
+ * @param snapshot the snapshot bitmap
*/
- @UiThread
- public OnInfoWindowCloseListener getOnInfoWindowCloseListener() {
- return onInfoWindowCloseListener;
- }
-
- //
- // User location
- //
+ void onSnapshotReady(Bitmap snapshot);
+ }
- /**
- * Returns the status of the my-location layer.
- *
- * @return True if the my-location layer is enabled, false otherwise.
- */
- @UiThread
- public boolean isMyLocationEnabled() {
- return myLocationEnabled;
- }
-
- /**
- * <p>
- * Enables or disables the my-location layer.
- * While enabled, the my-location layer continuously draws an indication of a user's current
- * location and bearing.
- * </p>
- * In order to use the my-location layer feature you need to request permission for either
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
- * or @link android.Manifest.permission#ACCESS_FINE_LOCATION.
- *
- * @param enabled True to enable; false to disable.
- */
- @UiThread
- public void setMyLocationEnabled(boolean enabled) {
- if (!mapView.isPermissionsAccepted()) {
- Log.e(MapboxConstants.TAG, "Could not activate user location tracking: "
- + "user did not accept the permission or permissions were not requested.");
- return;
- }
- myLocationEnabled = enabled;
- mapView.setMyLocationEnabled(enabled);
- }
-
- /**
- * Returns the currently displayed user location, or null if there is no location data available.
- *
- * @return The currently displayed user location.
- */
- @UiThread
- @Nullable
- public Location getMyLocation() {
- return mapView.getMyLocation();
- }
-
- /**
- * Sets a callback that's invoked when the the My Location view
- * (which signifies the user's location) changes location.
- *
- * @param listener The callback that's invoked when the user clicks on a marker.
- * To unset the callback, use null.
- */
- @UiThread
- public void setOnMyLocationChangeListener(@Nullable MapboxMap.OnMyLocationChangeListener listener) {
- mapView.setOnMyLocationChangeListener(listener);
- }
-
- /**
- * Sets a callback that's invoked when the location tracking mode changes.
- *
- * @param listener The callback that's invoked when the location tracking mode changes.
- * To unset the callback, use null.
- */
- @UiThread
- public void setOnMyLocationTrackingModeChangeListener(@Nullable MapboxMap.OnMyLocationTrackingModeChangeListener listener) {
- onMyLocationTrackingModeChangeListener = listener;
- }
-
- // used by MapView
- MapboxMap.OnMyLocationTrackingModeChangeListener getOnMyLocationTrackingModeChangeListener() {
- return onMyLocationTrackingModeChangeListener;
- }
-
- /**
- * Sets a callback that's invoked when the bearing tracking mode changes.
- *
- * @param listener The callback that's invoked when the bearing tracking mode changes.
- * To unset the callback, use null.
- */
- @UiThread
- public void setOnMyBearingTrackingModeChangeListener(@Nullable OnMyBearingTrackingModeChangeListener listener) {
- onMyBearingTrackingModeChangeListener = listener;
- }
-
- // used by MapView
- OnMyBearingTrackingModeChangeListener getOnMyBearingTrackingModeChangeListener() {
- return onMyBearingTrackingModeChangeListener;
- }
-
- MapView getMapView() {
- return mapView;
- }
-
- void setUiSettings(UiSettings uiSettings) {
- this.uiSettings = uiSettings;
- }
-
- void setProjection(Projection projection) {
- this.projection = projection;
- }
-
- //
- // Invalidate
- //
-
- /**
- * Triggers an invalidation of the map view.
- */
- public void invalidate() {
- mapView.invalidate();
- }
-
- /**
- * Takes a snapshot of the map.
- *
- * @param callback Callback method invoked when the snapshot is taken.
- * @param bitmap A pre-allocated bitmap.
- */
- @UiThread
- public void snapshot(@NonNull SnapshotReadyCallback callback, @Nullable final Bitmap bitmap) {
- mapView.snapshot(callback, bitmap);
- }
-
- /**
- * Takes a snapshot of the map.
- *
- * @param callback Callback method invoked when the snapshot is taken.
- */
- @UiThread
- public void snapshot(@NonNull SnapshotReadyCallback callback) {
- mapView.snapshot(callback, null);
- }
-
- /**
- * Queries the map for rendered features
- *
- * @param coordinates the point to query
- * @param layerIds optionally - only query these layers
- * @return the list of feature
- */
- @UiThread
- @NonNull
- public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates, @Nullable String... layerIds) {
- return mapView.getNativeMapView().queryRenderedFeatures(coordinates, layerIds);
- }
-
- /**
- * Queries the map for rendered features
- *
- * @param coordinates the box to query
- * @param layerIds optionally - only query these layers
- * @return the list of feature
- */
- @UiThread
- @NonNull
- public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates, @Nullable String... layerIds) {
- return mapView.getNativeMapView().queryRenderedFeatures(coordinates, layerIds);
- }
-
- //
- // Interfaces
- //
-
- /**
- * Interface definition for a callback to be invoked when the map is flinged.
- *
- * @see MapboxMap#setOnFlingListener(OnFlingListener)
- */
- public interface OnFlingListener {
- /**
- * Called when the map is flinged.
- */
- void onFling();
- }
-
- /**
- * Interface definition for a callback to be invoked when the map is scrolled.
- *
- * @see MapboxMap#setOnScrollListener(OnScrollListener)
- */
- public interface OnScrollListener {
- /**
- * Called when the map is scrolled.
- */
- void onScroll();
- }
-
- /**
- * Interface definition for a callback to be invoked when the camera changes position.
- */
- public interface OnCameraChangeListener {
- /**
- * Called after the camera position has changed. During an animation,
- * this listener may not be notified of intermediate camera positions.
- * It is always called for the final position in the animation.
- *
- * @param position The CameraPosition at the end of the last camera change.
- */
- void onCameraChange(CameraPosition position);
- }
-
- /**
- * Interface definition for a callback to be invoked when a frame is rendered to the map view.
- *
- * @see MapboxMap#setOnFpsChangedListener(OnFpsChangedListener)
- */
- public interface OnFpsChangedListener {
- /**
- * Called for every frame rendered to the map view.
- *
- * @param fps The average number of frames rendered over the last second.
- */
- void onFpsChanged(double fps);
- }
-
- /**
- * Interface definition for a callback to be invoked when the user clicks on the map view.
- *
- * @see MapboxMap#setOnMapClickListener(OnMapClickListener)
- */
- public interface OnMapClickListener {
- /**
- * Called when the user clicks on the map view.
- *
- * @param point The projected map coordinate the user clicked on.
- */
- void onMapClick(@NonNull LatLng point);
- }
-
- /**
- * Interface definition for a callback to be invoked when the user long clicks on the map view.
- *
- * @see MapboxMap#setOnMapLongClickListener(OnMapLongClickListener)
- */
- public interface OnMapLongClickListener {
- /**
- * Called when the user long clicks on the map view.
- *
- * @param point The projected map coordinate the user long clicked on.
- */
- void onMapLongClick(@NonNull LatLng point);
- }
-
- /**
- * Interface definition for a callback to be invoked when the user clicks on a marker.
- *
- * @see MapboxMap#setOnMarkerClickListener(OnMarkerClickListener)
- */
- public interface OnMarkerClickListener {
- /**
- * Called when the user clicks on a marker.
- *
- * @param marker The marker the user clicked on.
- * @return If true the listener has consumed the event and the info window will not be shown.
- */
- boolean onMarkerClick(@NonNull Marker marker);
- }
-
- /**
- * Interface definition for a callback to be invoked when the user clicks on an info window.
- *
- * @see MapboxMap#setOnInfoWindowClickListener(OnInfoWindowClickListener)
- */
- public interface OnInfoWindowClickListener {
- /**
- * Called when the user clicks on an info window.
- *
- * @param marker The marker of the info window the user clicked on.
- * @return If true the listener has consumed the event and the info window will not be closed.
- */
- boolean onInfoWindowClick(@NonNull Marker marker);
- }
-
- /**
- * Interface definition for a callback to be invoked when the user long presses on a marker's info window.
- *
- * @see MapboxMap#setOnInfoWindowClickListener(OnInfoWindowClickListener)
- */
- public interface OnInfoWindowLongClickListener {
-
- /**
- * Called when the user makes a long-press gesture on the marker's info window.
- *
- * @param marker The marker were the info window is attached to
- */
- void onInfoWindowLongClick(Marker marker);
- }
-
- /**
- * Interface definition for a callback to be invoked when a marker's info window is closed.
- *
- * @see MapboxMap#setOnInfoWindowCloseListener(OnInfoWindowCloseListener)
- */
- public interface OnInfoWindowCloseListener {
-
- /**
- * Called when the marker's info window is closed.
- *
- * @param marker The marker of the info window that was closed.
- */
- void onInfoWindowClose(Marker marker);
- }
-
- /**
- * Interface definition for a callback to be invoked when an info window will be shown.
- *
- * @see MapboxMap#setInfoWindowAdapter(InfoWindowAdapter)
- */
- public interface InfoWindowAdapter {
- /**
- * Called when an info window will be shown as a result of a marker click.
- *
- * @param marker The marker the user clicked on.
- * @return View to be shown as a info window. If null is returned the default
- * info window will be shown.
- */
- @Nullable
- View getInfoWindow(@NonNull Marker marker);
- }
-
- /**
- * Interface definition for a callback to be invoked when an MarkerView will be shown.
- *
- * @param <U> the instance type of MarkerView
- */
- public abstract static class MarkerViewAdapter<U extends MarkerView> {
-
- private Context context;
- private final Class<U> persistentClass;
- private final Pools.SimplePool<View> viewReusePool;
-
- /**
- * Create an instance of MarkerViewAdapter.
- *
- * @param context the context associated to a MapView
- */
- @SuppressWarnings("unchecked")
- public MarkerViewAdapter(Context context) {
- this.context = context;
- persistentClass = (Class<U>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
- viewReusePool = new Pools.SimplePool<>(10000);
- }
-
- /**
- * Called when an MarkerView will be added to the MapView.
- *
- * @param marker the model representing the MarkerView
- * @param convertView the reusable view
- * @param parent the parent ViewGroup of the convertview
- * @return the View that is adapted to the contents of MarkerView
- */
- @Nullable
- public abstract View getView(@NonNull U marker, @Nullable View convertView, @NonNull ViewGroup parent);
-
- /**
- * Called when an MarkerView is removed from the MapView or the View object is going to be reused.
- * <p>
- * This method should be used to reset an animated view back to it's original state for view reuse.
- * </p>
- * <p>
- * Returning true indicates you want to the view reuse to be handled automatically.
- * Returning false indicates you want to perform an animation and you are required calling {@link #releaseView(View)} yourself.
- * </p>
- *
- * @param marker the model representing the MarkerView
- * @param convertView the reusable view
- * @return true if you want reuse to occur automatically, false if you want to manage this yourself.
- */
- public boolean prepareViewForReuse(@NonNull MarkerView marker, @NonNull View convertView) {
- return true;
- }
-
- /**
- * Called when a MarkerView is selected from the MapView.
- * <p>
- * Returning true from this method indicates you want to move the MarkerView to the selected state.
- * Returning false indicates you want to animate the View first an manually select the MarkerView when appropriate.
- * </p>
- *
- * @param marker the model representing the MarkerView
- * @param convertView the reusable view
- * @param reselectionFromRecycling indicates if the onSelect callback is the initial selection
- * callback or that selection occurs due to recreation of selected marker
- * @return true if you want to select the Marker immediately, false if you want to manage this yourself.
- */
- public boolean onSelect(@NonNull U marker, @NonNull View convertView, boolean reselectionFromRecycling) {
- return true;
- }
-
- /**
- * Called when a MarkerView is deselected from the MapView.
- *
- * @param marker the model representing the MarkerView
- * @param convertView the reusable view
- */
- public void onDeselect(@NonNull U marker, @NonNull View convertView) {
- }
-
- /**
- * Returns the generic type of the used MarkerView.
- *
- * @return the generic type
- */
- public final Class<U> getMarkerClass() {
- return persistentClass;
- }
-
- /**
- * Returns the pool used to store reusable Views.
- *
- * @return the pool associated to this adapter
- */
- public final Pools.SimplePool<View> getViewReusePool() {
- return viewReusePool;
- }
-
- /**
- * Returns the context associated to the hosting MapView.
- *
- * @return the context used
- */
- public final Context getContext() {
- return context;
- }
-
- /**
- * Release a View to the ViewPool.
- *
- * @param view the view to be released
- */
- public final void releaseView(View view) {
- view.setVisibility(View.GONE);
- viewReusePool.release(view);
- }
- }
-
- /**
- * Interface definition for a callback to be invoked when the user clicks on a MarkerView.
- */
- public interface OnMarkerViewClickListener {
-
- /**
- * Called when the user clicks on a MarkerView.
- *
- * @param marker the MarkerView associated to the clicked View
- * @param view the clicked View
- * @param adapter the adapter used to adapt the MarkerView to the View
- * @return If true the listener has consumed the event and the info window will not be shown
- */
- boolean onMarkerClick(@NonNull Marker marker, @NonNull View view, @NonNull MarkerViewAdapter adapter);
- }
-
- /**
- * Interface definition for a callback to be invoked when the the My Location view changes location.
- *
- * @see MapboxMap#setOnMyLocationChangeListener(OnMyLocationChangeListener)
- */
- public interface OnMyLocationChangeListener {
- /**
- * Called when the location of the My Location view has changed
- * (be it latitude/longitude, bearing or accuracy).
- *
- * @param location The current location of the My Location view The type of map change event.
- */
- void onMyLocationChange(@Nullable Location location);
- }
-
- /**
- * Interface definition for a callback to be invoked when the the My Location tracking mode changes.
- *
- * @see MapView#setMyLocationTrackingMode(int)
- */
- public interface OnMyLocationTrackingModeChangeListener {
-
- /**
- * Called when the tracking mode of My Location tracking has changed
- *
- * @param myLocationTrackingMode the current active location tracking mode
- */
- void onMyLocationTrackingModeChange(@MyLocationTracking.Mode int myLocationTrackingMode);
- }
-
- /**
- * Interface definition for a callback to be invoked when the the My Location tracking mode changes.
- *
- * @see MapView#setMyLocationTrackingMode(int)
- */
- public interface OnMyBearingTrackingModeChangeListener {
-
- /**
- * Called when the tracking mode of My Bearing tracking has changed
- *
- * @param myBearingTrackingMode the current active bearing tracking mode
- */
- void onMyBearingTrackingModeChange(@MyBearingTracking.Mode int myBearingTrackingMode);
- }
-
- /**
- * Interface definition for a callback to be invoked when a task is complete or cancelled.
- */
- public interface CancelableCallback {
- /**
- * Invoked when a task is cancelled.
- */
- void onCancel();
-
- /**
- * Invoked when a task is complete.
- */
- void onFinish();
- }
-
- /**
- * Interface definition for a callback to be invoked when the snapshot has been taken.
- */
- public interface SnapshotReadyCallback {
- /**
- * Invoked when the snapshot has been taken.
- *
- * @param snapshot the snapshot bitmap
- */
- void onSnapshotReady(Bitmap snapshot);
- }
-
- private class MapChangeCameraPositionListener implements MapView.OnMapChangedListener {
-
- private static final long UPDATE_RATE_MS = 400;
- private long previousUpdateTimestamp = 0;
-
- @Override
- public void onMapChanged(@MapView.MapChange int change) {
- if (change >= MapView.REGION_WILL_CHANGE && change <= MapView.REGION_DID_CHANGE_ANIMATED) {
- invalidCameraPosition = true;
- long currentTime = SystemClock.elapsedRealtime();
- if (currentTime < previousUpdateTimestamp) {
- return;
- }
- invalidateCameraPosition();
- previousUpdateTimestamp = currentTime + UPDATE_RATE_MS;
- }
- }
- }
-}
+ //
+ // Used for instrumentation testing
+ //
+ Transform getTransform() {
+ return transform;
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
index a54d246913..518ef47329 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
@@ -34,1051 +34,1131 @@ import java.util.Arrays;
*/
public class MapboxMapOptions implements Parcelable {
- private static final float DIMENSION_SEVEN_DP = 7f;
- private static final float DIMENSION_TEN_DP = 10f;
- private static final float DIMENSION_SIXTEEN_DP = 16f;
- private static final float DIMENSION_SEVENTY_SIX_DP = 76f;
-
- private CameraPosition cameraPosition;
-
- private boolean debugActive;
-
- private boolean compassEnabled = true;
- private boolean fadeCompassFacingNorth = true;
- private int compassGravity = Gravity.TOP | Gravity.END;
- private int[] compassMargins;
-
- private boolean logoEnabled = true;
- private int logoGravity = Gravity.BOTTOM | Gravity.START;
- private int[] logoMargins;
-
- @ColorInt
- private int attributionTintColor = -1;
- private boolean attributionEnabled = true;
- private int attributionGravity = Gravity.BOTTOM;
- private int[] attributionMargins;
-
- private float minZoom = MapboxConstants.MINIMUM_ZOOM;
- private float maxZoom = MapboxConstants.MAXIMUM_ZOOM;
-
- private boolean rotateGesturesEnabled = true;
- private boolean scrollGesturesEnabled = true;
- private boolean tiltGesturesEnabled = true;
- private boolean zoomGesturesEnabled = true;
- private boolean zoomControlsEnabled = false;
-
- private boolean myLocationEnabled;
- private Drawable myLocationForegroundDrawable;
- private Drawable myLocationForegroundBearingDrawable;
- private Drawable myLocationBackgroundDrawable;
- private int myLocationForegroundTintColor;
- private int myLocationBackgroundTintColor;
- private int[] myLocationBackgroundPadding;
- private int myLocationAccuracyTintColor;
- private int myLocationAccuracyAlpha;
-
- private String apiBaseUrl;
-
- @Deprecated
- private boolean textureMode;
-
- private String style;
- @Deprecated
- private String accessToken;
-
- /**
- * Creates a new MapboxMapOptions object.
- */
- public MapboxMapOptions() {
- }
-
- private MapboxMapOptions(Parcel in) {
- cameraPosition = in.readParcelable(CameraPosition.class.getClassLoader());
- debugActive = in.readByte() != 0;
-
- compassEnabled = in.readByte() != 0;
- compassGravity = in.readInt();
- compassMargins = in.createIntArray();
- fadeCompassFacingNorth = in.readByte() != 0;
-
- logoEnabled = in.readByte() != 0;
- logoGravity = in.readInt();
- logoMargins = in.createIntArray();
-
- attributionEnabled = in.readByte() != 0;
- attributionGravity = in.readInt();
- attributionMargins = in.createIntArray();
- attributionTintColor = in.readInt();
-
- minZoom = in.readFloat();
- maxZoom = in.readFloat();
-
- rotateGesturesEnabled = in.readByte() != 0;
- scrollGesturesEnabled = in.readByte() != 0;
- tiltGesturesEnabled = in.readByte() != 0;
- zoomControlsEnabled = in.readByte() != 0;
- zoomGesturesEnabled = in.readByte() != 0;
-
- myLocationEnabled = in.readByte() != 0;
-
- Bitmap foregroundBitmap = in.readParcelable(getClass().getClassLoader());
- if (foregroundBitmap != null) {
- myLocationForegroundDrawable = new BitmapDrawable(foregroundBitmap);
- }
-
- Bitmap foregroundBearingBitmap = in.readParcelable(getClass().getClassLoader());
- if (foregroundBearingBitmap != null) {
- myLocationForegroundBearingDrawable = new BitmapDrawable(foregroundBearingBitmap);
- }
-
- Bitmap backgroundBitmap = in.readParcelable(getClass().getClassLoader());
- if (backgroundBitmap != null) {
- myLocationBackgroundDrawable = new BitmapDrawable(backgroundBitmap);
- }
-
- myLocationForegroundTintColor = in.readInt();
- myLocationBackgroundTintColor = in.readInt();
- myLocationBackgroundPadding = in.createIntArray();
- myLocationAccuracyAlpha = in.readInt();
- myLocationAccuracyTintColor = in.readInt();
-
- style = in.readString();
- accessToken = in.readString();
- apiBaseUrl = in.readString();
- textureMode = in.readByte() != 0;
- }
-
- public static Bitmap getBitmapFromDrawable(Drawable drawable) {
- if (drawable instanceof BitmapDrawable) {
- return ((BitmapDrawable) drawable).getBitmap();
- } else {
- Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
- drawable.draw(canvas);
- return bitmap;
- }
- }
-
- /**
- * Creates a MapboxMapsOptions from the attribute set.s
- *
- * @param context Context related to a map view.
- * @param attrs Attributeset containing configuration
- * @return the MapboxMapOptions created from attributes
- */
- public static MapboxMapOptions createFromAttributes(@NonNull Context context, @Nullable AttributeSet attrs) {
- MapboxMapOptions mapboxMapOptions = new MapboxMapOptions();
- float screenDensity = context.getResources().getDisplayMetrics().density;
- TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MapView, 0, 0);
- try {
- mapboxMapOptions.debugActive(typedArray.getBoolean(R.styleable.MapView_debug_active, false));
-
- mapboxMapOptions.camera(new CameraPosition.Builder(typedArray).build());
-
- mapboxMapOptions.accessToken(typedArray.getString(R.styleable.MapView_access_token));
- mapboxMapOptions.styleUrl(typedArray.getString(R.styleable.MapView_style_url));
- mapboxMapOptions.apiBaseUrl(typedArray.getString(R.styleable.MapView_api_base_url));
-
- mapboxMapOptions.zoomGesturesEnabled(typedArray.getBoolean(R.styleable.MapView_zoom_enabled, true));
- mapboxMapOptions.scrollGesturesEnabled(typedArray.getBoolean(R.styleable.MapView_scroll_enabled, true));
- mapboxMapOptions.rotateGesturesEnabled(typedArray.getBoolean(R.styleable.MapView_rotate_enabled, true));
- mapboxMapOptions.tiltGesturesEnabled(typedArray.getBoolean(R.styleable.MapView_tilt_enabled, true));
- mapboxMapOptions.zoomControlsEnabled(typedArray.getBoolean(R.styleable.MapView_zoom_controls_enabled, false));
-
- mapboxMapOptions.maxZoom(typedArray.getFloat(R.styleable.MapView_zoom_max, MapboxConstants.MAXIMUM_ZOOM));
- mapboxMapOptions.minZoom(typedArray.getFloat(R.styleable.MapView_zoom_min, MapboxConstants.MINIMUM_ZOOM));
-
- mapboxMapOptions.compassEnabled(typedArray.getBoolean(R.styleable.MapView_compass_enabled, true));
- mapboxMapOptions.compassGravity(typedArray.getInt(R.styleable.MapView_compass_gravity, Gravity.TOP | Gravity.END));
- mapboxMapOptions.compassMargins(new int[]{(int) (typedArray.getDimension(R.styleable.MapView_compass_margin_left, DIMENSION_TEN_DP) * screenDensity)
- , ((int) typedArray.getDimension(R.styleable.MapView_compass_margin_top, DIMENSION_TEN_DP * screenDensity))
- , ((int) typedArray.getDimension(R.styleable.MapView_compass_margin_right, DIMENSION_TEN_DP * screenDensity))
- , ((int) typedArray.getDimension(R.styleable.MapView_compass_margin_bottom, DIMENSION_TEN_DP * screenDensity))});
- mapboxMapOptions.compassFadesWhenFacingNorth(typedArray.getBoolean(R.styleable.MapView_compass_fade_facing_north, true));
-
- mapboxMapOptions.logoEnabled(typedArray.getBoolean(R.styleable.MapView_logo_enabled, true));
- mapboxMapOptions.logoGravity(typedArray.getInt(R.styleable.MapView_logo_gravity, Gravity.BOTTOM | Gravity.START));
- mapboxMapOptions.logoMargins(new int[]{(int) (typedArray.getDimension(R.styleable.MapView_logo_margin_left, DIMENSION_SIXTEEN_DP) * screenDensity)
- , (int) (typedArray.getDimension(R.styleable.MapView_logo_margin_top, DIMENSION_SIXTEEN_DP) * screenDensity)
- , (int) (typedArray.getDimension(R.styleable.MapView_logo_margin_right, DIMENSION_SIXTEEN_DP) * screenDensity)
- , (int) (typedArray.getDimension(R.styleable.MapView_logo_margin_bottom, DIMENSION_SIXTEEN_DP) * screenDensity)});
-
- mapboxMapOptions.attributionTintColor(typedArray.getColor(R.styleable.MapView_attribution_tint, -1));
- mapboxMapOptions.attributionEnabled(typedArray.getBoolean(R.styleable.MapView_attribution_enabled, true));
- mapboxMapOptions.attributionGravity(typedArray.getInt(R.styleable.MapView_attribution_gravity, Gravity.BOTTOM));
- mapboxMapOptions.attributionMargins(new int[]{(int) (typedArray.getDimension(R.styleable.MapView_attribution_margin_left, DIMENSION_SEVENTY_SIX_DP) * screenDensity)
- , (int) (typedArray.getDimension(R.styleable.MapView_attribution_margin_top, DIMENSION_SEVEN_DP) * screenDensity)
- , (int) (typedArray.getDimension(R.styleable.MapView_attribution_margin_right, DIMENSION_SEVEN_DP) * screenDensity)
- , (int) (typedArray.getDimension(R.styleable.MapView_attribution_margin_bottom, DIMENSION_SEVEN_DP) * screenDensity)});
-
- mapboxMapOptions.locationEnabled(typedArray.getBoolean(R.styleable.MapView_my_location_enabled, false));
- mapboxMapOptions.myLocationForegroundTintColor(typedArray.getColor(R.styleable.MapView_my_location_foreground_tint, Color.TRANSPARENT));
- mapboxMapOptions.myLocationBackgroundTintColor(typedArray.getColor(R.styleable.MapView_my_location_background_tint, Color.TRANSPARENT));
-
- Drawable foregroundDrawable = typedArray.getDrawable(R.styleable.MapView_my_location_foreground);
- if (foregroundDrawable == null) {
- foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.ic_mylocationview_normal);
- }
-
- Drawable foregroundBearingDrawable = typedArray.getDrawable(R.styleable.MapView_my_location_foreground_bearing);
- if (foregroundBearingDrawable == null) {
- foregroundBearingDrawable = ContextCompat.getDrawable(context, R.drawable.ic_mylocationview_bearing);
- }
-
- Drawable backgroundDrawable = typedArray.getDrawable(R.styleable.MapView_my_location_background);
- if (backgroundDrawable == null) {
- backgroundDrawable = ContextCompat.getDrawable(context, R.drawable.ic_mylocationview_background);
- }
-
- mapboxMapOptions.myLocationForegroundDrawables(foregroundDrawable, foregroundBearingDrawable);
- mapboxMapOptions.myLocationBackgroundDrawable(backgroundDrawable);
- mapboxMapOptions.myLocationBackgroundPadding(new int[]{(int) (typedArray.getDimension(R.styleable.MapView_my_location_background_left, 0) * screenDensity)
- , (int) (typedArray.getDimension(R.styleable.MapView_my_location_background_top, 0) * screenDensity)
- , (int) (typedArray.getDimension(R.styleable.MapView_my_location_background_right, 0) * screenDensity)
- , (int) (typedArray.getDimension(R.styleable.MapView_my_location_background_bottom, 0) * screenDensity)});
- mapboxMapOptions.myLocationAccuracyAlpha(typedArray.getInt(R.styleable.MapView_my_location_accuracy_alpha, 100));
- mapboxMapOptions.myLocationAccuracyTint(typedArray.getColor(R.styleable.MapView_my_location_accuracy_tint, ColorUtils.getPrimaryColor(context)));
- mapboxMapOptions.textureMode(typedArray.getBoolean(R.styleable.MapView_texture_mode, false));
- } finally {
- typedArray.recycle();
- }
- return mapboxMapOptions;
- }
-
- /**
- * Specifies the URL used for API endpoint.
- *
- * @param apiBaseUrl The base of our API endpoint
- * @return This
- */
- public MapboxMapOptions apiBaseUrl(String apiBaseUrl) {
- this.apiBaseUrl = apiBaseUrl;
- return this;
- }
-
- /**
- * Specifies a the initial camera position for the map view.
- *
- * @param cameraPosition Inital camera position
- * @return This
- */
- public MapboxMapOptions camera(CameraPosition cameraPosition) {
- this.cameraPosition = cameraPosition;
- return this;
- }
-
- /**
- * <p>
- * DEPRECATED @see MapboxAccountManager#start(String)
- * </p>
- * Specifies the accesstoken associated with a map view.
- *
- * @param accessToken Token to be used to access the service
- * @return This
- * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)}
- */
- @Deprecated
- public MapboxMapOptions accessToken(String accessToken) {
- this.accessToken = accessToken;
- return this;
- }
-
- /**
- * Specifies the style url associated with a map view.
- *
- * @param styleUrl Url to be used to load a style
- * @return This
- */
- public MapboxMapOptions styleUrl(String styleUrl) {
- style = styleUrl;
- return this;
- }
-
- /**
- * Specifies the used debug type for a map view.
- *
- * @param enabled True is debug is enabled
- * @return This
- */
- public MapboxMapOptions debugActive(boolean enabled) {
- debugActive = enabled;
- return this;
- }
-
- /**
- * Specifies the used minimum zoom level for a map view.
- *
- * @param minZoom Zoom level to be used
- * @return This
- */
- public MapboxMapOptions minZoom(float minZoom) {
- this.minZoom = minZoom;
- return this;
- }
-
- /**
- * Specifies the used maximum zoom level for a map view.
- *
- * @param maxZoom Zoom level to be used
- * @return This
- */
- public MapboxMapOptions maxZoom(float maxZoom) {
- this.maxZoom = maxZoom;
- return this;
- }
-
- /**
- * Specifies the visibility state of a compass for a map view.
- *
- * @param enabled True and compass is shown
- * @return This
- */
- public MapboxMapOptions compassEnabled(boolean enabled) {
- compassEnabled = enabled;
- return this;
- }
-
- /**
- * Specifies the gravity state of compass for a map view.
- *
- * @param gravity see {@link android.view.Gravity}
- * @return This
- */
- public MapboxMapOptions compassGravity(int gravity) {
- compassGravity = gravity;
- return this;
- }
-
- /**
- * Specifies the margin state of compass for a map view
- *
- * @param margins 4 long array for LTRB margins
- * @return This
- */
- public MapboxMapOptions compassMargins(int[] margins) {
- compassMargins = margins;
- return this;
- }
-
- /**
- * Specifies if the compass fades to invisible when facing north.
- * <p>
- * By default this value is true.
- * </p>
- *
- * @param compassFadeWhenFacingNorth true is compass fades to invisble
- * @return This
- */
- public MapboxMapOptions compassFadesWhenFacingNorth(boolean compassFadeWhenFacingNorth) {
- this.fadeCompassFacingNorth = compassFadeWhenFacingNorth;
- return this;
- }
-
- /**
- * Specifies the visibility state of a logo for a map view.
- *
- * @param enabled True and logo is shown
- * @return This
- */
- public MapboxMapOptions logoEnabled(boolean enabled) {
- logoEnabled = enabled;
- return this;
- }
-
- /**
- * Specifies the gravity state of logo for a map view.
- *
- * @param gravity see {@link android.view.Gravity}
- * @return This
- */
- public MapboxMapOptions logoGravity(int gravity) {
- logoGravity = gravity;
- return this;
- }
+ private static final float DIMENSION_SEVEN_DP = 7f;
+ private static final float DIMENSION_TEN_DP = 10f;
+ private static final float DIMENSION_SIXTEEN_DP = 16f;
+ private static final float DIMENSION_SEVENTY_SIX_DP = 76f;
- /**
- * Specifies the margin state of logo for a map view
- *
- * @param margins 4 long array for LTRB margins
- * @return This
- */
- public MapboxMapOptions logoMargins(int[] margins) {
- logoMargins = margins;
- return this;
- }
+ private CameraPosition cameraPosition;
- /**
- * Specifies the visibility state of a attribution for a map view.
- *
- * @param enabled True and attribution is shown
- * @return This
- */
- public MapboxMapOptions attributionEnabled(boolean enabled) {
- attributionEnabled = enabled;
- return this;
- }
+ private boolean debugActive;
- /**
- * Specifies the gravity state of attribution for a map view.
- *
- * @param gravity see {@link android.view.Gravity}
- * @return This
- */
- public MapboxMapOptions attributionGravity(int gravity) {
- attributionGravity = gravity;
- return this;
- }
+ private boolean compassEnabled = true;
+ private boolean fadeCompassFacingNorth = true;
+ private int compassGravity = Gravity.TOP | Gravity.END;
+ private int[] compassMargins;
- /**
- * Specifies the margin state of attribution for a map view
- *
- * @param margins 4 long array for LTRB margins
- * @return This
- */
- public MapboxMapOptions attributionMargins(int[] margins) {
- attributionMargins = margins;
- return this;
- }
+ private boolean logoEnabled = true;
+ private int logoGravity = Gravity.BOTTOM | Gravity.START;
+ private int[] logoMargins;
+
+ @ColorInt
+ private int attributionTintColor = -1;
+ private boolean attributionEnabled = true;
+ private int attributionGravity = Gravity.BOTTOM;
+ private int[] attributionMargins;
+
+ private double minZoom = MapboxConstants.MINIMUM_ZOOM;
+ private double maxZoom = MapboxConstants.MAXIMUM_ZOOM;
+
+ private boolean rotateGesturesEnabled = true;
+ private boolean scrollGesturesEnabled = true;
+ private boolean tiltGesturesEnabled = true;
+ private boolean zoomGesturesEnabled = true;
+ private boolean zoomControlsEnabled = false;
+
+ private boolean myLocationEnabled;
+ private Drawable myLocationForegroundDrawable;
+ private Drawable myLocationForegroundBearingDrawable;
+ private Drawable myLocationBackgroundDrawable;
+ private int myLocationForegroundTintColor;
+ private int myLocationBackgroundTintColor;
+ private int[] myLocationBackgroundPadding;
+ private int myLocationAccuracyTintColor;
+ private int myLocationAccuracyAlpha;
+
+ private String apiBaseUrl;
+
+ @Deprecated
+ private boolean textureMode;
+
+ private String style;
+
+ /**
+ * Creates a new MapboxMapOptions object.
+ */
+ public MapboxMapOptions() {
+ }
+
+ private MapboxMapOptions(Parcel in) {
+ cameraPosition = in.readParcelable(CameraPosition.class.getClassLoader());
+ debugActive = in.readByte() != 0;
+
+ compassEnabled = in.readByte() != 0;
+ compassGravity = in.readInt();
+ compassMargins = in.createIntArray();
+ fadeCompassFacingNorth = in.readByte() != 0;
+
+ logoEnabled = in.readByte() != 0;
+ logoGravity = in.readInt();
+ logoMargins = in.createIntArray();
+
+ attributionEnabled = in.readByte() != 0;
+ attributionGravity = in.readInt();
+ attributionMargins = in.createIntArray();
+ attributionTintColor = in.readInt();
+
+ minZoom = in.readDouble();
+ maxZoom = in.readDouble();
+
+ rotateGesturesEnabled = in.readByte() != 0;
+ scrollGesturesEnabled = in.readByte() != 0;
+ tiltGesturesEnabled = in.readByte() != 0;
+ zoomControlsEnabled = in.readByte() != 0;
+ zoomGesturesEnabled = in.readByte() != 0;
+
+ myLocationEnabled = in.readByte() != 0;
+
+ Bitmap foregroundBitmap = in.readParcelable(getClass().getClassLoader());
+ if (foregroundBitmap != null) {
+ myLocationForegroundDrawable = new BitmapDrawable(foregroundBitmap);
+ }
+
+ Bitmap foregroundBearingBitmap = in.readParcelable(getClass().getClassLoader());
+ if (foregroundBearingBitmap != null) {
+ myLocationForegroundBearingDrawable = new BitmapDrawable(foregroundBearingBitmap);
+ }
+
+ Bitmap backgroundBitmap = in.readParcelable(getClass().getClassLoader());
+ if (backgroundBitmap != null) {
+ myLocationBackgroundDrawable = new BitmapDrawable(backgroundBitmap);
+ }
+
+ myLocationForegroundTintColor = in.readInt();
+ myLocationBackgroundTintColor = in.readInt();
+ myLocationBackgroundPadding = in.createIntArray();
+ myLocationAccuracyAlpha = in.readInt();
+ myLocationAccuracyTintColor = in.readInt();
+
+ style = in.readString();
+ apiBaseUrl = in.readString();
+ textureMode = in.readByte() != 0;
+ }
+
+ public static Bitmap getBitmapFromDrawable(Drawable drawable) {
+ if (drawable instanceof BitmapDrawable) {
+ return ((BitmapDrawable) drawable).getBitmap();
+ } else {
+ Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ drawable.draw(canvas);
+ return bitmap;
+ }
+ }
+
+ /**
+ * Creates a MapboxMapsOptions from the attribute set.s
+ *
+ * @param context Context related to a map view.
+ * @param attrs Attributeset containing configuration
+ * @return the MapboxMapOptions created from attributes
+ */
+ public static MapboxMapOptions createFromAttributes(@NonNull Context context, @Nullable AttributeSet attrs) {
+ MapboxMapOptions mapboxMapOptions = new MapboxMapOptions();
+ float pxlRatio = context.getResources().getDisplayMetrics().density;
+ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.mapbox_MapView, 0, 0);
+ try {
+ mapboxMapOptions.camera(new CameraPosition.Builder(typedArray).build());
+ mapboxMapOptions.styleUrl(typedArray.getString(R.styleable.mapbox_MapView_mapbox_styleUrl));
+ mapboxMapOptions.apiBaseUrl(typedArray.getString(R.styleable.mapbox_MapView_mapbox_apiBaseUrl));
+
+ mapboxMapOptions.zoomGesturesEnabled(
+ typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiZoomGestures, true));
+ mapboxMapOptions.scrollGesturesEnabled(
+ typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiScrollGestures, true));
+ mapboxMapOptions.rotateGesturesEnabled(
+ typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiRotateGestures, true));
+ mapboxMapOptions.tiltGesturesEnabled(
+ typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiTiltGestures, true));
+ mapboxMapOptions.zoomControlsEnabled(
+ typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiZoomControls, false));
+
+ mapboxMapOptions.maxZoomPreference(typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraZoomMax,
+ MapboxConstants.MAXIMUM_ZOOM));
+ mapboxMapOptions.minZoomPreference(typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraZoomMin,
+ MapboxConstants.MINIMUM_ZOOM));
+
+ mapboxMapOptions.compassEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiCompass, true));
+ mapboxMapOptions.compassGravity(typedArray.getInt(R.styleable.mapbox_MapView_mapbox_uiCompassGravity,
+ Gravity.TOP | Gravity.END));
+ mapboxMapOptions.compassMargins(new int[] {
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiCompassMarginLeft,
+ DIMENSION_TEN_DP * pxlRatio)),
+ ((int) typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiCompassMarginTop,
+ DIMENSION_TEN_DP * pxlRatio)),
+ ((int) typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiCompassMarginRight,
+ DIMENSION_TEN_DP * pxlRatio)),
+ ((int) typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiCompassMarginBottom,
+ DIMENSION_TEN_DP * pxlRatio))});
+ mapboxMapOptions.compassFadesWhenFacingNorth(typedArray.getBoolean(
+ R.styleable.mapbox_MapView_mapbox_uiCompassFadeFacingNorth, true));
+
+ mapboxMapOptions.logoEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiLogo, true));
+ mapboxMapOptions.logoGravity(typedArray.getInt(R.styleable.mapbox_MapView_mapbox_uiLogoGravity,
+ Gravity.BOTTOM | Gravity.START));
+ mapboxMapOptions.logoMargins(new int[] {
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginLeft,
+ DIMENSION_SIXTEEN_DP * pxlRatio)),
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginTop,
+ DIMENSION_SIXTEEN_DP * pxlRatio)),
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginRight,
+ DIMENSION_SIXTEEN_DP * pxlRatio)),
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginBottom,
+ DIMENSION_SIXTEEN_DP * pxlRatio))});
+
+ mapboxMapOptions.attributionTintColor(typedArray.getColor(
+ R.styleable.mapbox_MapView_mapbox_uiAttributionTintColor, -1));
+ mapboxMapOptions.attributionEnabled(typedArray.getBoolean(
+ R.styleable.mapbox_MapView_mapbox_uiAttribution, true));
+ mapboxMapOptions.attributionGravity(typedArray.getInt(
+ R.styleable.mapbox_MapView_mapbox_uiAttributionGravity, Gravity.BOTTOM));
+ mapboxMapOptions.attributionMargins(new int[] {
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginLeft,
+ DIMENSION_SEVENTY_SIX_DP) * pxlRatio),
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginTop,
+ DIMENSION_SEVEN_DP * pxlRatio)),
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginRight,
+ DIMENSION_SEVEN_DP * pxlRatio)),
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginBottom,
+ DIMENSION_SEVEN_DP * pxlRatio))});
+
+ mapboxMapOptions.locationEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_myLocation, false));
+ mapboxMapOptions.myLocationForegroundTintColor(
+ typedArray.getColor(R.styleable.mapbox_MapView_mapbox_myLocationTintColor,
+ ColorUtils.getPrimaryColor(context)));
+ mapboxMapOptions.myLocationBackgroundTintColor(
+ typedArray.getColor(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundTintColor, Color.WHITE));
+
+ Drawable foregroundDrawable = typedArray.getDrawable(R.styleable.mapbox_MapView_mapbox_myLocationDrawable);
+ if (foregroundDrawable == null) {
+ foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_default);
+ }
+
+ Drawable foregroundBearingDrawable = typedArray.getDrawable(
+ R.styleable.mapbox_MapView_mapbox_myLocationBearingDrawable);
+ if (foregroundBearingDrawable == null) {
+ foregroundBearingDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_bearing);
+ }
+
+ Drawable backgroundDrawable = typedArray.getDrawable(
+ R.styleable.mapbox_MapView_mapbox_myLocationBackgroundDrawable);
+ if (backgroundDrawable == null) {
+ backgroundDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_bg_shape);
+ }
+
+ mapboxMapOptions.myLocationForegroundDrawables(foregroundDrawable, foregroundBearingDrawable);
+ mapboxMapOptions.myLocationBackgroundDrawable(backgroundDrawable);
+ mapboxMapOptions.myLocationBackgroundPadding(new int[] {
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundMarginLeft,
+ 0) * pxlRatio),
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundMarginTop,
+ 0) * pxlRatio),
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundMarginRight,
+ 0) * pxlRatio),
+ (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundMarginBottom,
+ 0) * pxlRatio)
+ });
+ mapboxMapOptions.myLocationAccuracyAlpha(
+ typedArray.getInt(R.styleable.mapbox_MapView_mapbox_myLocationAccuracyAlpha, 100));
+ mapboxMapOptions.myLocationAccuracyTint(
+ typedArray.getColor(R.styleable.mapbox_MapView_mapbox_myLocationAccuracyTintColor,
+ ColorUtils.getPrimaryColor(context)));
+ mapboxMapOptions.textureMode(
+ typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_renderTextureMode, false));
+ } finally {
+ typedArray.recycle();
+ }
+ return mapboxMapOptions;
+ }
+
+ /**
+ * Specifies the URL used for API endpoint.
+ *
+ * @param apiBaseUrl The base of our API endpoint
+ * @return This
+ */
+ public MapboxMapOptions apiBaseUrl(String apiBaseUrl) {
+ this.apiBaseUrl = apiBaseUrl;
+ return this;
+ }
+
+ /**
+ * Specifies a the initial camera position for the map view.
+ *
+ * @param cameraPosition Inital camera position
+ * @return This
+ */
+ public MapboxMapOptions camera(CameraPosition cameraPosition) {
+ this.cameraPosition = cameraPosition;
+ return this;
+ }
+
+ /**
+ * Specifies the style url associated with a map view.
+ *
+ * @param styleUrl Url to be used to load a style
+ * @return This
+ */
+ public MapboxMapOptions styleUrl(String styleUrl) {
+ style = styleUrl;
+ return this;
+ }
+
+ /**
+ * Specifies the used debug type for a map view.
+ *
+ * @param enabled True is debug is enabled
+ * @return This
+ */
+ public MapboxMapOptions debugActive(boolean enabled) {
+ debugActive = enabled;
+ return this;
+ }
+
+ /**
+ * Specifies the used minimum zoom level for a map view.
+ *
+ * @param minZoom Zoom level to be used
+ * @return This
+ */
+ public MapboxMapOptions minZoomPreference(double minZoom) {
+ this.minZoom = minZoom;
+ return this;
+ }
+
+ /**
+ * Specifies the used maximum zoom level for a map view.
+ *
+ * @param maxZoom Zoom level to be used
+ * @return This
+ */
+ public MapboxMapOptions maxZoomPreference(double maxZoom) {
+ this.maxZoom = maxZoom;
+ return this;
+ }
+
+ /**
+ * Specifies the visibility state of a mapbox_compass_icon for a map view.
+ *
+ * @param enabled True and mapbox_compass_icon is shown
+ * @return This
+ */
+ public MapboxMapOptions compassEnabled(boolean enabled) {
+ compassEnabled = enabled;
+ return this;
+ }
+
+ /**
+ * Specifies the gravity state of mapbox_compass_icon for a map view.
+ *
+ * @param gravity see {@link android.view.Gravity}
+ * @return This
+ */
+ public MapboxMapOptions compassGravity(int gravity) {
+ compassGravity = gravity;
+ return this;
+ }
+
+ /**
+ * Specifies the margin state of mapbox_compass_icon for a map view
+ *
+ * @param margins 4 long array for LTRB margins
+ * @return This
+ */
+ public MapboxMapOptions compassMargins(int[] margins) {
+ compassMargins = margins;
+ return this;
+ }
+
+ /**
+ * Specifies if the mapbox_compass_icon fades to invisible when facing north.
+ * <p>
+ * By default this value is true.
+ * </p>
+ *
+ * @param compassFadeWhenFacingNorth true is mapbox_compass_icon fades to invisble
+ * @return This
+ */
+ public MapboxMapOptions compassFadesWhenFacingNorth(boolean compassFadeWhenFacingNorth) {
+ this.fadeCompassFacingNorth = compassFadeWhenFacingNorth;
+ return this;
+ }
+
+ /**
+ * Specifies the visibility state of a logo for a map view.
+ *
+ * @param enabled True and logo is shown
+ * @return This
+ */
+ public MapboxMapOptions logoEnabled(boolean enabled) {
+ logoEnabled = enabled;
+ return this;
+ }
+
+ /**
+ * Specifies the gravity state of logo for a map view.
+ *
+ * @param gravity see {@link android.view.Gravity}
+ * @return This
+ */
+ public MapboxMapOptions logoGravity(int gravity) {
+ logoGravity = gravity;
+ return this;
+ }
+
+ /**
+ * Specifies the margin state of logo for a map view
+ *
+ * @param margins 4 long array for LTRB margins
+ * @return This
+ */
+ public MapboxMapOptions logoMargins(int[] margins) {
+ logoMargins = margins;
+ return this;
+ }
+
+ /**
+ * Specifies the visibility state of a attribution for a map view.
+ *
+ * @param enabled True and attribution is shown
+ * @return This
+ */
+ public MapboxMapOptions attributionEnabled(boolean enabled) {
+ attributionEnabled = enabled;
+ return this;
+ }
+
+ /**
+ * Specifies the gravity state of attribution for a map view.
+ *
+ * @param gravity see {@link android.view.Gravity}
+ * @return This
+ */
+ public MapboxMapOptions attributionGravity(int gravity) {
+ attributionGravity = gravity;
+ return this;
+ }
+
+ /**
+ * Specifies the margin state of attribution for a map view
+ *
+ * @param margins 4 long array for LTRB margins
+ * @return This
+ */
+ public MapboxMapOptions attributionMargins(int[] margins) {
+ attributionMargins = margins;
+ return this;
+ }
+
+ /**
+ * Specifies the tint color of the attribution for a map view
+ *
+ * @param color integer resembling a color
+ * @return This
+ */
+ public MapboxMapOptions attributionTintColor(@ColorInt int color) {
+ attributionTintColor = color;
+ return this;
+ }
+
+ /**
+ * Specifies if the rotate gesture is enabled for a map view.
+ *
+ * @param enabled True and gesture will be enabled
+ * @return This
+ */
+ public MapboxMapOptions rotateGesturesEnabled(boolean enabled) {
+ rotateGesturesEnabled = enabled;
+ return this;
+ }
+
+ /**
+ * Specifies if the scroll gesture is enabled for a map view.
+ *
+ * @param enabled True and gesture will be enabled
+ * @return This
+ */
+ public MapboxMapOptions scrollGesturesEnabled(boolean enabled) {
+ scrollGesturesEnabled = enabled;
+ return this;
+ }
+
+ /**
+ * Specifies if the tilt gesture is enabled for a map view.
+ *
+ * @param enabled True and gesture will be enabled
+ * @return This
+ */
+ public MapboxMapOptions tiltGesturesEnabled(boolean enabled) {
+ tiltGesturesEnabled = enabled;
+ return this;
+ }
+
+ /**
+ * Specifies if the zoom controls are enabled for a map view.
+ *
+ * @param enabled True and gesture will be enabled
+ * @return This
+ */
+ public MapboxMapOptions zoomControlsEnabled(boolean enabled) {
+ zoomControlsEnabled = enabled;
+ return this;
+ }
+
+ /**
+ * Specifies if the zoom gesture is enabled for a map view.
+ *
+ * @param enabled True and gesture will be enabled
+ * @return This
+ */
+ public MapboxMapOptions zoomGesturesEnabled(boolean enabled) {
+ zoomGesturesEnabled = enabled;
+ return this;
+ }
+
+ /**
+ * Specifies if the user location view is enabled for a map view.
+ *
+ * @param locationEnabled True and gesture will be enabled
+ * @return This
+ */
+ public MapboxMapOptions locationEnabled(boolean locationEnabled) {
+ this.myLocationEnabled = locationEnabled;
+ return this;
+ }
+
+ /**
+ * Set the foreground drawables of the MyLocationView.
+ *
+ * @param myLocationForegroundDrawable the drawable to show as foreground without bearing
+ * @param myLocationBearingDrawable the drawable to show as foreground when bearing is disabled
+ * @return This
+ */
+ public MapboxMapOptions myLocationForegroundDrawables(Drawable myLocationForegroundDrawable,
+ Drawable myLocationBearingDrawable) {
+ this.myLocationForegroundDrawable = myLocationForegroundDrawable;
+ this.myLocationForegroundBearingDrawable = myLocationBearingDrawable;
+ return this;
+ }
+
+ /**
+ * Set the foreground drawable of the MyLocationView.
+ * <p>
+ * The same drawable will be used for both bearing as non bearing modes.
+ * </p>
+ *
+ * @param myLocationForegroundDrawable the drawable to show as foreground
+ * @return This
+ */
+ public MapboxMapOptions myLocationForegroundDrawable(Drawable myLocationForegroundDrawable) {
+ this.myLocationForegroundDrawable = myLocationForegroundDrawable;
+ return this;
+ }
+
+ /**
+ * Set the background drawable of MyLocationView.
+ * <p>
+ * Padding can be added to provide an offset to the background.
+ * </p>
+ *
+ * @param myLocationBackgroundDrawable the drawable to show as background
+ * @return This
+ */
+ public MapboxMapOptions myLocationBackgroundDrawable(Drawable myLocationBackgroundDrawable) {
+ this.myLocationBackgroundDrawable = myLocationBackgroundDrawable;
+ return this;
+ }
+
+ /**
+ * Set the foreground tint color of MyLocationView.
+ * <p>
+ * The color will tint both the foreground and the bearing foreground drawable.
+ * </p>
+ *
+ * @param myLocationForegroundTintColor the color to tint the foreground drawable
+ * @return This
+ */
+ public MapboxMapOptions myLocationForegroundTintColor(@ColorInt int myLocationForegroundTintColor) {
+ this.myLocationForegroundTintColor = myLocationForegroundTintColor;
+ return this;
+ }
+
+ /**
+ * Set the background tint color of MyLocationView.
+ *
+ * @param myLocationBackgroundTintColor the color to tint the background
+ * @return This
+ */
+ public MapboxMapOptions myLocationBackgroundTintColor(@ColorInt int myLocationBackgroundTintColor) {
+ this.myLocationBackgroundTintColor = myLocationBackgroundTintColor;
+ return this;
+ }
+
+ /**
+ * Set the MyLocationView padding.
+ *
+ * @param myLocationBackgroundPadding the color to tint the background
+ * @return This
+ */
+ public MapboxMapOptions myLocationBackgroundPadding(int[] myLocationBackgroundPadding) {
+ this.myLocationBackgroundPadding = myLocationBackgroundPadding;
+ return this;
+ }
+
+ /**
+ * Set the MyLocationView accuracy circle tint color.
+ *
+ * @param myLocationAccuracyTintColor the color to tint the accuracy circle
+ * @return This
+ */
+ public MapboxMapOptions myLocationAccuracyTint(@ColorInt int myLocationAccuracyTintColor) {
+ this.myLocationAccuracyTintColor = myLocationAccuracyTintColor;
+ return this;
+ }
+
+ /**
+ * Set the MyLocationView accuracy alpha value.
+ *
+ * @param alpha the alpha value
+ * @return This
+ */
+ public MapboxMapOptions myLocationAccuracyAlpha(@IntRange(from = 0, to = 255) int alpha) {
+ this.myLocationAccuracyAlpha = alpha;
+ return this;
+ }
+
+ /**
+ * Enable TextureView as rendered surface.
+ * <p>
+ * Since the 4.2.0 release we replaced our TextureView with an SurfaceView implemenation.
+ * Enabling this option will use the deprecated TextureView instead.
+ * </p>
+ *
+ * @param textureMode True to enable texture mode
+ * @return This
+ * @deprecated As of the 4.2.0 release, using TextureView is deprecated.
+ */
+ public MapboxMapOptions textureMode(boolean textureMode) {
+ this.textureMode = textureMode;
+ return this;
+ }
+
+ /**
+ * Get the current configured API endpoint base URL.
+ *
+ * @return Base URL to be used API endpoint.
+ */
+ public String getApiBaseUrl() {
+ return apiBaseUrl;
+ }
+
+ /**
+ * Get the current configured initial camera position for a map view.
+ *
+ * @return CameraPosition to be initially used.
+ */
+ public CameraPosition getCamera() {
+ return cameraPosition;
+ }
+
+ /**
+ * Get the current configured min zoom for a map view.
+ *
+ * @return Mininum zoom level to be used.
+ */
+ public double getMinZoomPreference() {
+ return minZoom;
+ }
+
+ /**
+ * Get the current configured maximum zoom for a map view.
+ *
+ * @return Maximum zoom to be used.
+ */
+ public double getMaxZoomPreference() {
+ return maxZoom;
+ }
+
+ /**
+ * Get the current configured visibility state for mapbox_compass_icon for a map view.
+ *
+ * @return Visibility state of the mapbox_compass_icon
+ */
+ public boolean getCompassEnabled() {
+ return compassEnabled;
+ }
+
+ /**
+ * Get the current configured gravity state for mapbox_compass_icon for a map view.
+ *
+ * @return Gravity state of the mapbox_compass_icon
+ */
+ public int getCompassGravity() {
+ return compassGravity;
+ }
+
+ /**
+ * Get the current configured margins for mapbox_compass_icon for a map view.
+ *
+ * @return Margins state of the mapbox_compass_icon
+ */
+ public int[] getCompassMargins() {
+ return compassMargins;
+ }
+
+ /**
+ * Get the current configured state for fading the mapbox_compass_icon when facing north.
+ *
+ * @return True if mapbox_compass_icon fades to invisible when facing north
+ */
+ public boolean getCompassFadeFacingNorth() {
+ return fadeCompassFacingNorth;
+ }
+
+ /**
+ * Get the current configured visibility state for mapbox_compass_icon for a map view.
+ *
+ * @return Visibility state of the mapbox_compass_icon
+ */
+ public boolean getLogoEnabled() {
+ return logoEnabled;
+ }
+
+ /**
+ * Get the current configured gravity state for logo for a map view.
+ *
+ * @return Gravity state of the logo
+ */
+ public int getLogoGravity() {
+ return logoGravity;
+ }
+
+ /**
+ * Get the current configured margins for logo for a map view.
+ *
+ * @return Margins state of the logo
+ */
+ public int[] getLogoMargins() {
+ return logoMargins;
+ }
+
+ /**
+ * Get the current configured style url for a map view.
+ *
+ * @return Style url to be used.
+ */
+ public String getStyle() {
+ return style;
+ }
+
+ /**
+ * Get the current configured rotate gesture state for a map view.
+ *
+ * @return True indicates gesture is enabled
+ */
+ public boolean getRotateGesturesEnabled() {
+ return rotateGesturesEnabled;
+ }
+
+ /**
+ * Get the current configured scroll gesture state for a map view.
+ *
+ * @return True indicates gesture is enabled
+ */
+ public boolean getScrollGesturesEnabled() {
+ return scrollGesturesEnabled;
+ }
+
+ /**
+ * Get the current configured tilt gesture state for a map view.
+ *
+ * @return True indicates gesture is enabled
+ */
+ public boolean getTiltGesturesEnabled() {
+ return tiltGesturesEnabled;
+ }
+
+ /**
+ * Get the current configured zoom controls state for a map view.
+ *
+ * @return True indicates gesture is enabled
+ */
+ public boolean getZoomControlsEnabled() {
+ return zoomControlsEnabled;
+ }
+
+ /**
+ * Get the current configured zoom gesture state for a map view.
+ *
+ * @return True indicates gesture is enabled
+ */
+ public boolean getZoomGesturesEnabled() {
+ return zoomGesturesEnabled;
+ }
+
+ /**
+ * Get the current configured visibility state for attribution for a map view.
+ *
+ * @return Visibility state of the attribution
+ */
+ public boolean getAttributionEnabled() {
+ return attributionEnabled;
+ }
+
+ /**
+ * Get the current configured gravity state for attribution for a map view.
+ *
+ * @return Gravity state of the logo
+ */
+ public int getAttributionGravity() {
+ return attributionGravity;
+ }
+
+ /**
+ * Get the current configured margins for attribution for a map view.
+ *
+ * @return Margins state of the logo
+ */
+ public int[] getAttributionMargins() {
+ return attributionMargins;
+ }
+
+ /**
+ * Get the current configured tint color for attribution for a map view.
+ *
+ * @return the tint color
+ */
+ @ColorInt
+ public int getAttributionTintColor() {
+ return attributionTintColor;
+ }
+
+ /**
+ * Get the current configured user location view state for a map view.
+ *
+ * @return True and user location will be shown
+ */
+ public boolean getLocationEnabled() {
+ return myLocationEnabled;
+ }
+
+ /**
+ * Get the current configured MyLocationView foreground drawable.
+ *
+ * @return the drawable used as foreground
+ */
+ public Drawable getMyLocationForegroundDrawable() {
+ return myLocationForegroundDrawable;
+ }
+
+ /**
+ * Get the current configured MyLocationView foreground bearing drawable.
+ *
+ * @return the drawable used as foreground when bearing is enabled
+ */
+ public Drawable getMyLocationForegroundBearingDrawable() {
+ return myLocationForegroundBearingDrawable;
+ }
+
+ /**
+ * Get the current configured MyLocationView background drawable.
+ *
+ * @return the drawable used as background
+ */
+ public Drawable getMyLocationBackgroundDrawable() {
+ return myLocationBackgroundDrawable;
+ }
+
+ /**
+ * Get the current configured MyLocationView foreground tint color.
+ *
+ * @return the tint color
+ */
+ public int getMyLocationForegroundTintColor() {
+ return myLocationForegroundTintColor;
+ }
+
+ /**
+ * Get the current configured MyLocationView background tint color.
+ *
+ * @return the tint color
+ */
+ public int getMyLocationBackgroundTintColor() {
+ return myLocationBackgroundTintColor;
+ }
+
+ /**
+ * Get the current configured MyLocationView background padding.
+ *
+ * @return an array describing the padding in a LTRB manner
+ */
+ public int[] getMyLocationBackgroundPadding() {
+ return myLocationBackgroundPadding;
+ }
+
+ /**
+ * Get the current configured MyLocationView accuracy circle color tint value.
+ *
+ * @return the tint color
+ */
+ public int getMyLocationAccuracyTintColor() {
+ return myLocationAccuracyTintColor;
+ }
+
+ /**
+ * Get the current configured MyLocationView accuracy circle alpha value.
+ *
+ * @return the alpha value
+ */
+ public int getMyLocationAccuracyAlpha() {
+ return myLocationAccuracyAlpha;
+ }
+
+ /**
+ * Get the current configured debug state for a map view.
+ *
+ * @return True indicates debug is enabled.
+ */
+ public boolean getDebugActive() {
+ return debugActive;
+ }
+
+ /**
+ * Returns true if TextureView is being used a render view.
+ *
+ * @return True if TextureView is used.
+ * @deprecated As of the 4.2.0 release, using TextureView is deprecated.
+ */
+ public boolean getTextureMode() {
+ return textureMode;
+ }
+
+ public static final Parcelable.Creator<MapboxMapOptions> CREATOR = new Parcelable.Creator<MapboxMapOptions>() {
+ public MapboxMapOptions createFromParcel(Parcel in) {
+ return new MapboxMapOptions(in);
+ }
+
+ public MapboxMapOptions[] newArray(int size) {
+ return new MapboxMapOptions[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(cameraPosition, flags);
+ dest.writeByte((byte) (debugActive ? 1 : 0));
+
+ dest.writeByte((byte) (compassEnabled ? 1 : 0));
+ dest.writeInt(compassGravity);
+ dest.writeIntArray(compassMargins);
+ dest.writeByte((byte) (fadeCompassFacingNorth ? 1 : 0));
+
+ dest.writeByte((byte) (logoEnabled ? 1 : 0));
+ dest.writeInt(logoGravity);
+ dest.writeIntArray(logoMargins);
+
+ dest.writeByte((byte) (attributionEnabled ? 1 : 0));
+ dest.writeInt(attributionGravity);
+ dest.writeIntArray(attributionMargins);
+ dest.writeInt(attributionTintColor);
+
+ dest.writeDouble(minZoom);
+ dest.writeDouble(maxZoom);
+
+ dest.writeByte((byte) (rotateGesturesEnabled ? 1 : 0));
+ dest.writeByte((byte) (scrollGesturesEnabled ? 1 : 0));
+ dest.writeByte((byte) (tiltGesturesEnabled ? 1 : 0));
+ dest.writeByte((byte) (zoomControlsEnabled ? 1 : 0));
+ dest.writeByte((byte) (zoomGesturesEnabled ? 1 : 0));
+
+ dest.writeByte((byte) (myLocationEnabled ? 1 : 0));
+
+ dest.writeParcelable(myLocationForegroundDrawable != null
+ ? getBitmapFromDrawable(myLocationForegroundDrawable) : null, flags);
+ dest.writeParcelable(myLocationForegroundBearingDrawable != null
+ ? getBitmapFromDrawable(myLocationForegroundBearingDrawable) : null, flags);
+ dest.writeParcelable(myLocationBackgroundDrawable != null
+ ? getBitmapFromDrawable(myLocationBackgroundDrawable) : null, flags);
+ dest.writeInt(myLocationForegroundTintColor);
+ dest.writeInt(myLocationBackgroundTintColor);
+ dest.writeIntArray(myLocationBackgroundPadding);
+ dest.writeInt(myLocationAccuracyAlpha);
+ dest.writeInt(myLocationAccuracyTintColor);
+
+ dest.writeString(style);
+ dest.writeString(apiBaseUrl);
+ dest.writeByte((byte) (textureMode ? 1 : 0));
+ }
- /**
- * Specifies the tint color of the attribution for a map view
- *
- * @param color integer resembling a color
- * @return This
- */
- public MapboxMapOptions attributionTintColor(@ColorInt int color) {
- attributionTintColor = color;
- return this;
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
}
-
- /**
- * Specifies if the rotate gesture is enabled for a map view.
- *
- * @param enabled True and gesture will be enabled
- * @return This
- */
- public MapboxMapOptions rotateGesturesEnabled(boolean enabled) {
- rotateGesturesEnabled = enabled;
- return this;
+ if (o == null || getClass() != o.getClass()) {
+ return false;
}
- /**
- * Specifies if the scroll gesture is enabled for a map view.
- *
- * @param enabled True and gesture will be enabled
- * @return This
- */
- public MapboxMapOptions scrollGesturesEnabled(boolean enabled) {
- scrollGesturesEnabled = enabled;
- return this;
- }
+ MapboxMapOptions options = (MapboxMapOptions) o;
- /**
- * Specifies if the tilt gesture is enabled for a map view.
- *
- * @param enabled True and gesture will be enabled
- * @return This
- */
- public MapboxMapOptions tiltGesturesEnabled(boolean enabled) {
- tiltGesturesEnabled = enabled;
- return this;
+ if (debugActive != options.debugActive) {
+ return false;
}
-
- /**
- * Specifies if the zoom controls are enabled for a map view.
- *
- * @param enabled True and gesture will be enabled
- * @return This
- */
- public MapboxMapOptions zoomControlsEnabled(boolean enabled) {
- zoomControlsEnabled = enabled;
- return this;
+ if (compassEnabled != options.compassEnabled) {
+ return false;
}
-
- /**
- * Specifies if the zoom gesture is enabled for a map view.
- *
- * @param enabled True and gesture will be enabled
- * @return This
- */
- public MapboxMapOptions zoomGesturesEnabled(boolean enabled) {
- zoomGesturesEnabled = enabled;
- return this;
+ if (fadeCompassFacingNorth != options.fadeCompassFacingNorth) {
+ return false;
}
-
- /**
- * Specifies if the user location view is enabled for a map view.
- *
- * @param locationEnabled True and gesture will be enabled
- * @return This
- */
- public MapboxMapOptions locationEnabled(boolean locationEnabled) {
- this.myLocationEnabled = locationEnabled;
- return this;
+ if (compassGravity != options.compassGravity) {
+ return false;
}
-
- /**
- * Set the foreground drawables of the MyLocationView.
- *
- * @param myLocationForegroundDrawable the drawable to show as foreground without bearing
- * @param myLocationBearingDrawable the drawable to show as foreground when bearing is disabled
- * @return This
- */
- public MapboxMapOptions myLocationForegroundDrawables(Drawable myLocationForegroundDrawable, Drawable myLocationBearingDrawable) {
- this.myLocationForegroundDrawable = myLocationForegroundDrawable;
- this.myLocationForegroundBearingDrawable = myLocationBearingDrawable;
- return this;
- }
-
- /**
- * Set the foreground drawable of the MyLocationView.
- * <p>
- * The same drawable will be used for both bearing as non bearing modes.
- * </p>
- *
- * @param myLocationForegroundDrawable the drawable to show as foreground
- * @return This
- */
- public MapboxMapOptions myLocationForegroundDrawable(Drawable myLocationForegroundDrawable) {
- this.myLocationForegroundDrawable = myLocationForegroundDrawable;
- return this;
+ if (logoEnabled != options.logoEnabled) {
+ return false;
}
-
- /**
- * Set the background drawable of MyLocationView.
- * <p>
- * Padding can be added to provide an offset to the background.
- * </p>
- *
- * @param myLocationBackgroundDrawable the drawable to show as background
- * @return This
- */
- public MapboxMapOptions myLocationBackgroundDrawable(Drawable myLocationBackgroundDrawable) {
- this.myLocationBackgroundDrawable = myLocationBackgroundDrawable;
- return this;
+ if (logoGravity != options.logoGravity) {
+ return false;
}
-
- /**
- * Set the foreground tint color of MyLocationView.
- * <p>
- * The color will tint both the foreground and the bearing foreground drawable.
- * </p>
- *
- * @param myLocationForegroundTintColor the color to tint the foreground drawable
- * @return This
- */
- public MapboxMapOptions myLocationForegroundTintColor(@ColorInt int myLocationForegroundTintColor) {
- this.myLocationForegroundTintColor = myLocationForegroundTintColor;
- return this;
+ if (attributionTintColor != options.attributionTintColor) {
+ return false;
}
-
- /**
- * Set the background tint color of MyLocationView.
- *
- * @param myLocationBackgroundTintColor the color to tint the background
- * @return This
- */
- public MapboxMapOptions myLocationBackgroundTintColor(@ColorInt int myLocationBackgroundTintColor) {
- this.myLocationBackgroundTintColor = myLocationBackgroundTintColor;
- return this;
+ if (attributionEnabled != options.attributionEnabled) {
+ return false;
}
-
- /**
- * Set the MyLocationView padding.
- *
- * @param myLocationBackgroundPadding the color to tint the background
- * @return This
- */
- public MapboxMapOptions myLocationBackgroundPadding(int[] myLocationBackgroundPadding) {
- this.myLocationBackgroundPadding = myLocationBackgroundPadding;
- return this;
+ if (attributionGravity != options.attributionGravity) {
+ return false;
}
-
- /**
- * Set the MyLocationView accuracy circle tint color.
- *
- * @param myLocationAccuracyTintColor the color to tint the accuracy circle
- * @return This
- */
- public MapboxMapOptions myLocationAccuracyTint(@ColorInt int myLocationAccuracyTintColor) {
- this.myLocationAccuracyTintColor = myLocationAccuracyTintColor;
- return this;
- }
-
- /**
- * Set the MyLocationView accuracy alpha value.
- *
- * @param alpha the alpha value
- * @return This
- */
- public MapboxMapOptions myLocationAccuracyAlpha(@IntRange(from = 0, to = 255) int alpha) {
- this.myLocationAccuracyAlpha = alpha;
- return this;
- }
-
- /**
- * Enable TextureView as rendered surface.
- * <p>
- * Since the 4.2.0 release we replaced our TextureView with an SurfaceView implemenation.
- * Enabling this option will use the deprecated TextureView instead.
- * </p>
- *
- * @param textureMode True to enable texture mode
- * @return This
- * @deprecated As of the 4.2.0 release, using TextureView is deprecated.
- */
- public MapboxMapOptions textureMode(boolean textureMode) {
- this.textureMode = textureMode;
- return this;
- }
-
- /**
- * Get the current configured API endpoint base URL.
- *
- * @return Base URL to be used API endpoint.
- */
- public String getApiBaseUrl() {
- return apiBaseUrl;
- }
-
- /**
- * Get the current configured initial camera position for a map view.
- *
- * @return CameraPosition to be initially used.
- */
- public CameraPosition getCamera() {
- return cameraPosition;
- }
-
- /**
- * Get the current configured min zoom for a map view.
- *
- * @return Mininum zoom level to be used.
- */
- public float getMinZoom() {
- return minZoom;
- }
-
- /**
- * Get the current configured maximum zoom for a map view.
- *
- * @return Maximum zoom to be used.
- */
- public float getMaxZoom() {
- return maxZoom;
- }
-
- /**
- * Get the current configured visibility state for compass for a map view.
- *
- * @return Visibility state of the compass
- */
- public boolean getCompassEnabled() {
- return compassEnabled;
- }
-
- /**
- * Get the current configured gravity state for compass for a map view.
- *
- * @return Gravity state of the compass
- */
- public int getCompassGravity() {
- return compassGravity;
- }
-
- /**
- * Get the current configured margins for compass for a map view.
- *
- * @return Margins state of the compass
- */
- public int[] getCompassMargins() {
- return compassMargins;
- }
-
- /**
- * Get the current configured state for fading the compass when facing north.
- *
- * @return True if compass fades to invisible when facing north
- */
- public boolean getCompassFadeFacingNorth() {
- return fadeCompassFacingNorth;
- }
-
- /**
- * Get the current configured visibility state for compass for a map view.
- *
- * @return Visibility state of the compass
- */
- public boolean getLogoEnabled() {
- return logoEnabled;
- }
-
- /**
- * Get the current configured gravity state for logo for a map view.
- *
- * @return Gravity state of the logo
- */
- public int getLogoGravity() {
- return logoGravity;
- }
-
- /**
- * Get the current configured margins for logo for a map view.
- *
- * @return Margins state of the logo
- */
- public int[] getLogoMargins() {
- return logoMargins;
- }
-
- /**
- * <p>
- * DEPRECATED @see MapboxAccountManager#start(String)
- * </p>
- * Get the current configured access token for a map view.
- *
- * @return Access token to be used.
- */
- @Deprecated
- public String getAccessToken() {
- return accessToken;
- }
-
- /**
- * Get the current configured style url for a map view.
- *
- * @return Style url to be used.
- */
- public String getStyle() {
- return style;
- }
-
- /**
- * Get the current configured rotate gesture state for a map view.
- *
- * @return True indicates gesture is enabled
- */
- public boolean getRotateGesturesEnabled() {
- return rotateGesturesEnabled;
- }
-
- /**
- * Get the current configured scroll gesture state for a map view.
- *
- * @return True indicates gesture is enabled
- */
- public boolean getScrollGesturesEnabled() {
- return scrollGesturesEnabled;
- }
-
- /**
- * Get the current configured tilt gesture state for a map view.
- *
- * @return True indicates gesture is enabled
- */
- public boolean getTiltGesturesEnabled() {
- return tiltGesturesEnabled;
- }
-
- /**
- * Get the current configured zoom controls state for a map view.
- *
- * @return True indicates gesture is enabled
- */
- public boolean getZoomControlsEnabled() {
- return zoomControlsEnabled;
- }
-
- /**
- * Get the current configured zoom gesture state for a map view.
- *
- * @return True indicates gesture is enabled
- */
- public boolean getZoomGesturesEnabled() {
- return zoomGesturesEnabled;
- }
-
- /**
- * Get the current configured visibility state for attribution for a map view.
- *
- * @return Visibility state of the attribution
- */
- public boolean getAttributionEnabled() {
- return attributionEnabled;
- }
-
- /**
- * Get the current configured gravity state for attribution for a map view.
- *
- * @return Gravity state of the logo
- */
- public int getAttributionGravity() {
- return attributionGravity;
- }
-
- /**
- * Get the current configured margins for attribution for a map view.
- *
- * @return Margins state of the logo
- */
- public int[] getAttributionMargins() {
- return attributionMargins;
- }
-
- /**
- * Get the current configured tint color for attribution for a map view.
- *
- * @return the tint color
- */
- @ColorInt
- public int getAttributionTintColor() {
- return attributionTintColor;
- }
-
- /**
- * Get the current configured user location view state for a map view.
- *
- * @return True and user location will be shown
- */
- public boolean getLocationEnabled() {
- return myLocationEnabled;
- }
-
- /**
- * Get the current configured MyLocationView foreground drawable.
- *
- * @return the drawable used as foreground
- */
- public Drawable getMyLocationForegroundDrawable() {
- return myLocationForegroundDrawable;
- }
-
- /**
- * Get the current configured MyLocationView foreground bearing drawable.
- *
- * @return the drawable used as foreground when bearing is enabled
- */
- public Drawable getMyLocationForegroundBearingDrawable() {
- return myLocationForegroundBearingDrawable;
- }
-
- /**
- * Get the current configured MyLocationView background drawable.
- *
- * @return the drawable used as background
- */
- public Drawable getMyLocationBackgroundDrawable() {
- return myLocationBackgroundDrawable;
- }
-
- /**
- * Get the current configured MyLocationView foreground tint color.
- *
- * @return the tint color
- */
- public int getMyLocationForegroundTintColor() {
- return myLocationForegroundTintColor;
- }
-
- /**
- * Get the current configured MyLocationView background tint color.
- *
- * @return the tint color
- */
- public int getMyLocationBackgroundTintColor() {
- return myLocationBackgroundTintColor;
- }
-
- /**
- * Get the current configured MyLocationView background padding.
- *
- * @return an array describing the padding in a LTRB manner
- */
- public int[] getMyLocationBackgroundPadding() {
- return myLocationBackgroundPadding;
- }
-
- /**
- * Get the current configured MyLocationView accuracy circle color tint value.
- *
- * @return the tint color
- */
- public int getMyLocationAccuracyTintColor() {
- return myLocationAccuracyTintColor;
- }
-
- /**
- * Get the current configured MyLocationView accuracy circle alpha value.
- *
- * @return the alpha value
- */
- public int getMyLocationAccuracyAlpha() {
- return myLocationAccuracyAlpha;
- }
-
- /**
- * Get the current configured debug state for a map view.
- *
- * @return True indicates debug is enabled.
- */
- public boolean getDebugActive() {
- return debugActive;
- }
-
- /**
- * Returns true if TextureView is being used a render view.
- *
- * @return True if TextureView is used.
- * @deprecated As of the 4.2.0 release, using TextureView is deprecated.
- */
- public boolean getTextureMode() {
- return textureMode;
- }
-
- public static final Parcelable.Creator<MapboxMapOptions> CREATOR
- = new Parcelable.Creator<MapboxMapOptions>() {
- public MapboxMapOptions createFromParcel(Parcel in) {
- return new MapboxMapOptions(in);
- }
-
- public MapboxMapOptions[] newArray(int size) {
- return new MapboxMapOptions[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(cameraPosition, flags);
- dest.writeByte((byte) (debugActive ? 1 : 0));
-
- dest.writeByte((byte) (compassEnabled ? 1 : 0));
- dest.writeInt(compassGravity);
- dest.writeIntArray(compassMargins);
- dest.writeByte((byte) (fadeCompassFacingNorth ? 1 : 0));
-
- dest.writeByte((byte) (logoEnabled ? 1 : 0));
- dest.writeInt(logoGravity);
- dest.writeIntArray(logoMargins);
-
- dest.writeByte((byte) (attributionEnabled ? 1 : 0));
- dest.writeInt(attributionGravity);
- dest.writeIntArray(attributionMargins);
- dest.writeInt(attributionTintColor);
-
- dest.writeFloat(minZoom);
- dest.writeFloat(maxZoom);
-
- dest.writeByte((byte) (rotateGesturesEnabled ? 1 : 0));
- dest.writeByte((byte) (scrollGesturesEnabled ? 1 : 0));
- dest.writeByte((byte) (tiltGesturesEnabled ? 1 : 0));
- dest.writeByte((byte) (zoomControlsEnabled ? 1 : 0));
- dest.writeByte((byte) (zoomGesturesEnabled ? 1 : 0));
-
- dest.writeByte((byte) (myLocationEnabled ? 1 : 0));
-
- dest.writeParcelable(myLocationForegroundDrawable != null ? getBitmapFromDrawable(myLocationForegroundDrawable) : null, flags);
- dest.writeParcelable(myLocationForegroundBearingDrawable != null ? getBitmapFromDrawable(myLocationForegroundBearingDrawable) : null, flags);
- dest.writeParcelable(myLocationBackgroundDrawable != null ? getBitmapFromDrawable(myLocationBackgroundDrawable) : null, flags);
- dest.writeInt(myLocationForegroundTintColor);
- dest.writeInt(myLocationBackgroundTintColor);
- dest.writeIntArray(myLocationBackgroundPadding);
- dest.writeInt(myLocationAccuracyAlpha);
- dest.writeInt(myLocationAccuracyTintColor);
-
- dest.writeString(style);
- dest.writeString(accessToken);
- dest.writeString(apiBaseUrl);
- dest.writeByte((byte) (textureMode ? 1 : 0));
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- MapboxMapOptions options = (MapboxMapOptions) o;
-
- if (debugActive != options.debugActive) return false;
- if (compassEnabled != options.compassEnabled) return false;
- if (fadeCompassFacingNorth != options.fadeCompassFacingNorth) return false;
- if (compassGravity != options.compassGravity) return false;
- if (logoEnabled != options.logoEnabled) return false;
- if (logoGravity != options.logoGravity) return false;
- if (attributionTintColor != options.attributionTintColor) return false;
- if (attributionEnabled != options.attributionEnabled) return false;
- if (attributionGravity != options.attributionGravity) return false;
- if (Float.compare(options.minZoom, minZoom) != 0) return false;
- if (Float.compare(options.maxZoom, maxZoom) != 0) return false;
- if (rotateGesturesEnabled != options.rotateGesturesEnabled) return false;
- if (scrollGesturesEnabled != options.scrollGesturesEnabled) return false;
- if (tiltGesturesEnabled != options.tiltGesturesEnabled) return false;
- if (zoomGesturesEnabled != options.zoomGesturesEnabled) return false;
- if (zoomControlsEnabled != options.zoomControlsEnabled) return false;
- if (myLocationEnabled != options.myLocationEnabled) return false;
- if (myLocationForegroundTintColor != options.myLocationForegroundTintColor) return false;
- if (myLocationBackgroundTintColor != options.myLocationBackgroundTintColor) return false;
- if (myLocationAccuracyTintColor != options.myLocationAccuracyTintColor) return false;
- if (myLocationAccuracyAlpha != options.myLocationAccuracyAlpha) return false;
- if (cameraPosition != null ? !cameraPosition.equals(options.cameraPosition) : options.cameraPosition != null)
- return false;
- if (!Arrays.equals(compassMargins, options.compassMargins)) return false;
- if (!Arrays.equals(logoMargins, options.logoMargins)) return false;
- if (!Arrays.equals(attributionMargins, options.attributionMargins)) return false;
- if (myLocationForegroundDrawable != null ? !myLocationForegroundDrawable.equals(options.myLocationForegroundDrawable) : options.myLocationForegroundDrawable != null)
- return false;
- if (myLocationForegroundBearingDrawable != null ? !myLocationForegroundBearingDrawable.equals(options.myLocationForegroundBearingDrawable) : options.myLocationForegroundBearingDrawable != null)
- return false;
- if (myLocationBackgroundDrawable != null ? !myLocationBackgroundDrawable.equals(options.myLocationBackgroundDrawable) : options.myLocationBackgroundDrawable != null)
- return false;
- if (!Arrays.equals(myLocationBackgroundPadding, options.myLocationBackgroundPadding))
- return false;
- if (style != null ? !style.equals(options.style) : options.style != null) return false;
- if (apiBaseUrl != null ? !apiBaseUrl.equals(options.apiBaseUrl) : options.apiBaseUrl != null)
- return false;
- return accessToken != null ? accessToken.equals(options.accessToken) : options.accessToken == null;
-
- }
-
- @Override
- public int hashCode() {
- int result = cameraPosition != null ? cameraPosition.hashCode() : 0;
- result = 31 * result + (debugActive ? 1 : 0);
- result = 31 * result + (compassEnabled ? 1 : 0);
- result = 31 * result + (fadeCompassFacingNorth ? 1 : 0);
- result = 31 * result + compassGravity;
- result = 31 * result + Arrays.hashCode(compassMargins);
- result = 31 * result + (logoEnabled ? 1 : 0);
- result = 31 * result + logoGravity;
- result = 31 * result + Arrays.hashCode(logoMargins);
- result = 31 * result + attributionTintColor;
- result = 31 * result + (attributionEnabled ? 1 : 0);
- result = 31 * result + attributionGravity;
- result = 31 * result + Arrays.hashCode(attributionMargins);
- result = 31 * result + (minZoom != +0.0f ? Float.floatToIntBits(minZoom) : 0);
- result = 31 * result + (maxZoom != +0.0f ? Float.floatToIntBits(maxZoom) : 0);
- result = 31 * result + (rotateGesturesEnabled ? 1 : 0);
- result = 31 * result + (scrollGesturesEnabled ? 1 : 0);
- result = 31 * result + (tiltGesturesEnabled ? 1 : 0);
- result = 31 * result + (zoomGesturesEnabled ? 1 : 0);
- result = 31 * result + (zoomControlsEnabled ? 1 : 0);
- result = 31 * result + (myLocationEnabled ? 1 : 0);
- result = 31 * result + (myLocationForegroundDrawable != null ? myLocationForegroundDrawable.hashCode() : 0);
- result = 31 * result + (myLocationForegroundBearingDrawable != null ? myLocationForegroundBearingDrawable.hashCode() : 0);
- result = 31 * result + (myLocationBackgroundDrawable != null ? myLocationBackgroundDrawable.hashCode() : 0);
- result = 31 * result + myLocationForegroundTintColor;
- result = 31 * result + myLocationBackgroundTintColor;
- result = 31 * result + Arrays.hashCode(myLocationBackgroundPadding);
- result = 31 * result + myLocationAccuracyTintColor;
- result = 31 * result + myLocationAccuracyAlpha;
- result = 31 * result + (style != null ? style.hashCode() : 0);
- result = 31 * result + (accessToken != null ? accessToken.hashCode() : 0);
- result = 31 * result + (apiBaseUrl != null ? apiBaseUrl.hashCode() : 0);
- return result;
+ if (Double.compare(options.minZoom, minZoom) != 0) {
+ return false;
}
-}
+ if (Double.compare(options.maxZoom, maxZoom) != 0) {
+ return false;
+ }
+ if (rotateGesturesEnabled != options.rotateGesturesEnabled) {
+ return false;
+ }
+ if (scrollGesturesEnabled != options.scrollGesturesEnabled) {
+ return false;
+ }
+ if (tiltGesturesEnabled != options.tiltGesturesEnabled) {
+ return false;
+ }
+ if (zoomGesturesEnabled != options.zoomGesturesEnabled) {
+ return false;
+ }
+ if (zoomControlsEnabled != options.zoomControlsEnabled) {
+ return false;
+ }
+ if (myLocationEnabled != options.myLocationEnabled) {
+ return false;
+ }
+ if (myLocationForegroundTintColor != options.myLocationForegroundTintColor) {
+ return false;
+ }
+ if (myLocationBackgroundTintColor != options.myLocationBackgroundTintColor) {
+ return false;
+ }
+ if (myLocationAccuracyTintColor != options.myLocationAccuracyTintColor) {
+ return false;
+ }
+ if (myLocationAccuracyAlpha != options.myLocationAccuracyAlpha) {
+ return false;
+ }
+ if (cameraPosition != null ? !cameraPosition.equals(options.cameraPosition) : options.cameraPosition != null) {
+ return false;
+ }
+ if (!Arrays.equals(compassMargins, options.compassMargins)) {
+ return false;
+ }
+ if (!Arrays.equals(logoMargins, options.logoMargins)) {
+ return false;
+ }
+ if (!Arrays.equals(attributionMargins, options.attributionMargins)) {
+ return false;
+ }
+ if (myLocationForegroundDrawable != null
+ ? !myLocationForegroundDrawable.equals(options.myLocationForegroundDrawable)
+ : options.myLocationForegroundDrawable != null) {
+ return false;
+ }
+ if (myLocationForegroundBearingDrawable != null
+ ? !myLocationForegroundBearingDrawable.equals(options.myLocationForegroundBearingDrawable)
+ : options.myLocationForegroundBearingDrawable != null) {
+ return false;
+ }
+ if (myLocationBackgroundDrawable != null
+ ? !myLocationBackgroundDrawable.equals(options.myLocationBackgroundDrawable)
+ : options.myLocationBackgroundDrawable != null) {
+ return false;
+ }
+ if (!Arrays.equals(myLocationBackgroundPadding, options.myLocationBackgroundPadding)) {
+ return false;
+ }
+ if (style != null ? !style.equals(options.style) : options.style != null) {
+ return false;
+ }
+ if (apiBaseUrl != null ? !apiBaseUrl.equals(options.apiBaseUrl) : options.apiBaseUrl != null) {
+ return false;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int result;
+ long temp;
+ result = cameraPosition != null ? cameraPosition.hashCode() : 0;
+ result = 31 * result + (debugActive ? 1 : 0);
+ result = 31 * result + (compassEnabled ? 1 : 0);
+ result = 31 * result + (fadeCompassFacingNorth ? 1 : 0);
+ result = 31 * result + compassGravity;
+ result = 31 * result + Arrays.hashCode(compassMargins);
+ result = 31 * result + (logoEnabled ? 1 : 0);
+ result = 31 * result + logoGravity;
+ result = 31 * result + Arrays.hashCode(logoMargins);
+ result = 31 * result + attributionTintColor;
+ result = 31 * result + (attributionEnabled ? 1 : 0);
+ result = 31 * result + attributionGravity;
+ result = 31 * result + Arrays.hashCode(attributionMargins);
+ temp = Double.doubleToLongBits(minZoom);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(maxZoom);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ result = 31 * result + (rotateGesturesEnabled ? 1 : 0);
+ result = 31 * result + (scrollGesturesEnabled ? 1 : 0);
+ result = 31 * result + (tiltGesturesEnabled ? 1 : 0);
+ result = 31 * result + (zoomGesturesEnabled ? 1 : 0);
+ result = 31 * result + (zoomControlsEnabled ? 1 : 0);
+ result = 31 * result + (myLocationEnabled ? 1 : 0);
+ result = 31 * result + (myLocationForegroundDrawable != null ? myLocationForegroundDrawable.hashCode() : 0);
+ result = 31 * result + (myLocationForegroundBearingDrawable != null
+ ? myLocationForegroundBearingDrawable.hashCode() : 0);
+ result = 31 * result + (myLocationBackgroundDrawable != null ? myLocationBackgroundDrawable.hashCode() : 0);
+ result = 31 * result + myLocationForegroundTintColor;
+ result = 31 * result + myLocationBackgroundTintColor;
+ result = 31 * result + Arrays.hashCode(myLocationBackgroundPadding);
+ result = 31 * result + myLocationAccuracyTintColor;
+ result = 31 * result + myLocationAccuracyAlpha;
+ result = 31 * result + (apiBaseUrl != null ? apiBaseUrl.hashCode() : 0);
+ result = 31 * result + (textureMode ? 1 : 0);
+ result = 31 * result + (style != null ? style.hashCode() : 0);
+ return result;
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
index 4e0ce33c5b..05d1bf1750 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
@@ -3,13 +3,14 @@ package com.mapbox.mapboxsdk.maps;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.text.TextUtils;
import android.util.DisplayMetrics;
-import android.util.Log;
import android.view.Surface;
import com.mapbox.mapboxsdk.annotations.Icon;
@@ -30,741 +31,1159 @@ import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import timber.log.Timber;
// Class that wraps the native methods for convenience
final class NativeMapView {
- //
- // Static members
- //
+ // Flag to indicating destroy was called
+ private boolean destroyed = false;
- //
- // Instance members
- //
+ // Holds the pointer to JNI NativeMapView
+ private long nativeMapViewPtr = 0;
- boolean destroyed = false;
+ // Used for callbacks
+ private MapView mapView;
- // Holds the pointer to JNI NativeMapView
- private long nativeMapViewPtr = 0;
+ // Device density
+ private final float pixelRatio;
- // Used for callbacks
- private MapView mapView;
+ // Listeners for Map change events
+ private CopyOnWriteArrayList<MapView.OnMapChangedListener> onMapChangedListeners;
- private final float pixelRatio;
+ // Listener invoked to return a bitmap of the map
+ private SnapshotRequest snapshotRequest;
- //
- // Static methods
- //
+ //
+ // Static methods
+ //
- static {
- System.loadLibrary("mapbox-gl");
- }
+ static {
+ System.loadLibrary("mapbox-gl");
+ }
+
+ //
+ // Constructors
+ //
- //
- // Constructors
- //
+ public NativeMapView(MapView mapView) {
+ Context context = mapView.getContext();
+ String dataPath = OfflineManager.getDatabasePath(context);
- public NativeMapView(MapView mapView) {
- Context context = mapView.getContext();
- String dataPath = OfflineManager.getDatabasePath(context);
+ // With the availability of offline, we're unifying the ambient (cache) and the offline
+ // databases to be in the same folder, outside cache, to avoid automatic deletion from
+ // the system
+ String cachePath = dataPath;
- // With the availability of offline, we're unifying the ambient (cache) and the offline
- // databases to be in the same folder, outside cache, to avoid automatic deletion from
- // the system
- String cachePath = dataPath;
+ pixelRatio = context.getResources().getDisplayMetrics().density;
+ String apkPath = context.getPackageCodePath();
+ int availableProcessors = Runtime.getRuntime().availableProcessors();
+ ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+ ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ activityManager.getMemoryInfo(memoryInfo);
+ long totalMemory = memoryInfo.availMem;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ totalMemory = memoryInfo.totalMem;
+ }
- pixelRatio = context.getResources().getDisplayMetrics().density;
- String apkPath = context.getPackageCodePath();
- int availableProcessors = Runtime.getRuntime().availableProcessors();
- ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
- ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- activityManager.getMemoryInfo(memoryInfo);
- long totalMemory = memoryInfo.availMem;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- totalMemory = memoryInfo.totalMem;
- }
+ if (availableProcessors < 0) {
+ throw new IllegalArgumentException("availableProcessors cannot be negative.");
+ }
- if (availableProcessors < 0) {
- throw new IllegalArgumentException("availableProcessors cannot be negative.");
- }
+ if (totalMemory < 0) {
+ throw new IllegalArgumentException("totalMemory cannot be negative.");
+ }
+ onMapChangedListeners = new CopyOnWriteArrayList<>();
+ this.mapView = mapView;
+ nativeMapViewPtr = nativeCreate(cachePath, dataPath, apkPath, pixelRatio, availableProcessors, totalMemory);
+ }
- if (totalMemory < 0) {
- throw new IllegalArgumentException("totalMemory cannot be negative.");
- }
+ //
+ // Methods
+ //
- this.mapView = mapView;
- nativeMapViewPtr = nativeCreate(cachePath, dataPath, apkPath, pixelRatio, availableProcessors, totalMemory);
+ private boolean isDestroyedOn(String callingMethod) {
+ if (destroyed && !TextUtils.isEmpty(callingMethod)) {
+ Timber.e(String.format(MapboxConstants.MAPBOX_LOCALE,
+ "You're calling `%s` after the `MapView` was destroyed, were you invoking it after `onDestroy()`?",
+ callingMethod));
}
+ return destroyed;
+ }
- //
- // Methods
- //
+ public void destroy() {
+ nativeDestroy(nativeMapViewPtr);
+ nativeMapViewPtr = 0;
+ mapView = null;
+ destroyed = true;
+ }
- public void destroy() {
- nativeDestroy(nativeMapViewPtr);
- nativeMapViewPtr = 0;
- mapView = null;
- destroyed = true;
+ public void initializeDisplay() {
+ if (isDestroyedOn("initializeDisplay")) {
+ return;
}
+ nativeInitializeDisplay(nativeMapViewPtr);
+ }
- public boolean wasDestroyed() {
- return destroyed;
+ public void terminateDisplay() {
+ if (isDestroyedOn("terminateDisplay")) {
+ return;
}
+ nativeTerminateDisplay(nativeMapViewPtr);
+ }
- public void initializeDisplay() {
- nativeInitializeDisplay(nativeMapViewPtr);
+ public void initializeContext() {
+ if (isDestroyedOn("initializeContext")) {
+ return;
}
+ nativeInitializeContext(nativeMapViewPtr);
+ }
- public void terminateDisplay() {
- nativeTerminateDisplay(nativeMapViewPtr);
+ public void terminateContext() {
+ if (isDestroyedOn("terminateContext")) {
+ return;
}
+ nativeTerminateContext(nativeMapViewPtr);
+ }
- public void initializeContext() {
- nativeInitializeContext(nativeMapViewPtr);
+ public void createSurface(Surface surface) {
+ if (isDestroyedOn("createSurface")) {
+ return;
}
+ nativeCreateSurface(nativeMapViewPtr, surface);
+ }
- public void terminateContext() {
- nativeTerminateContext(nativeMapViewPtr);
+ public void destroySurface() {
+ if (isDestroyedOn("destroySurface")) {
+ return;
}
+ nativeDestroySurface(nativeMapViewPtr);
+ }
- public void createSurface(Surface surface) {
- nativeCreateSurface(nativeMapViewPtr, surface);
+ public void update() {
+ if (isDestroyedOn("update")) {
+ return;
}
+ nativeUpdate(nativeMapViewPtr);
+ }
- public void destroySurface() {
- nativeDestroySurface(nativeMapViewPtr);
+ public void render() {
+ if (isDestroyedOn("render")) {
+ return;
}
+ nativeRender(nativeMapViewPtr);
+ }
- public void update() {
- nativeUpdate(nativeMapViewPtr);
+ public void resizeView(int width, int height) {
+ if (isDestroyedOn("resizeView")) {
+ return;
}
+ width = (int) (width / pixelRatio);
+ height = (int) (height / pixelRatio);
- public void render() {
- nativeRender(nativeMapViewPtr);
+ if (width < 0) {
+ throw new IllegalArgumentException("width cannot be negative.");
}
- public void resizeView(int width, int height) {
- if (width < 0) {
- throw new IllegalArgumentException("width cannot be negative.");
- }
+ if (height < 0) {
+ throw new IllegalArgumentException("height cannot be negative.");
+ }
- if (height < 0) {
- throw new IllegalArgumentException("height cannot be negative.");
- }
+ if (width > 65535) {
+ // we have seen edge cases where devices return incorrect values #6111
+ Timber.e("Device returned an out of range width size, "
+ + "capping value at 65535 instead of " + width);
+ width = 65535;
+ }
- if (width > 65535) {
- // we have seen edge cases where devices return incorrect values #6111
- Log.e(MapboxConstants.TAG, "Device returned an out of range width size, " +
- "capping value at 65535 instead of " + width);
- width = 65535;
- }
+ if (height > 65535) {
+ // we have seen edge cases where devices return incorrect values #6111
+ Timber.e("Device returned an out of range height size, "
+ + "capping value at 65535 instead of " + height);
+ height = 65535;
+ }
+ nativeViewResize(nativeMapViewPtr, width, height);
+ }
- if (height > 65535) {
- // we have seen edge cases where devices return incorrect values #6111
- Log.e(MapboxConstants.TAG, "Device returned an out of range height size, " +
- "capping value at 65535 instead of " + height);
- height = 65535;
- }
- nativeViewResize(nativeMapViewPtr, width, height);
+ public void resizeFramebuffer(int fbWidth, int fbHeight) {
+ if (isDestroyedOn("resizeFramebuffer")) {
+ return;
+ }
+ if (fbWidth < 0) {
+ throw new IllegalArgumentException("fbWidth cannot be negative.");
}
- public void resizeFramebuffer(int fbWidth, int fbHeight) {
- if (fbWidth < 0) {
- throw new IllegalArgumentException("fbWidth cannot be negative.");
- }
+ if (fbHeight < 0) {
+ throw new IllegalArgumentException("fbHeight cannot be negative.");
+ }
- if (fbHeight < 0) {
- throw new IllegalArgumentException("fbHeight cannot be negative.");
- }
+ if (fbWidth > 65535) {
+ throw new IllegalArgumentException(
+ "fbWidth cannot be greater than 65535.");
+ }
- if (fbWidth > 65535) {
- throw new IllegalArgumentException(
- "fbWidth cannot be greater than 65535.");
- }
+ if (fbHeight > 65535) {
+ throw new IllegalArgumentException(
+ "fbHeight cannot be greater than 65535.");
+ }
+ nativeFramebufferResize(nativeMapViewPtr, fbWidth, fbHeight);
+ }
- if (fbHeight > 65535) {
- throw new IllegalArgumentException(
- "fbHeight cannot be greater than 65535.");
- }
- nativeFramebufferResize(nativeMapViewPtr, fbWidth, fbHeight);
+ public void addClass(String clazz) {
+ if (isDestroyedOn("addClass")) {
+ return;
}
+ nativeAddClass(nativeMapViewPtr, clazz);
+ }
- public void addClass(String clazz) {
- nativeAddClass(nativeMapViewPtr, clazz);
+ public void removeClass(String clazz) {
+ if (isDestroyedOn("removeClass")) {
+ return;
}
+ nativeRemoveClass(nativeMapViewPtr, clazz);
+ }
- public void removeClass(String clazz) {
- nativeRemoveClass(nativeMapViewPtr, clazz);
+ public boolean hasClass(String clazz) {
+ if (isDestroyedOn("hasClass")) {
+ return false;
}
+ return nativeHasClass(nativeMapViewPtr, clazz);
+ }
- public boolean hasClass(String clazz) {
- return nativeHasClass(nativeMapViewPtr, clazz);
+ public void setClasses(List<String> classes) {
+ if (isDestroyedOn("setClasses")) {
+ return;
}
+ nativeSetClasses(nativeMapViewPtr, classes);
+ }
- public void setClasses(List<String> classes) {
- nativeSetClasses(nativeMapViewPtr, classes);
+ public List<String> getClasses() {
+ if (isDestroyedOn("getClasses")) {
+ return new ArrayList<>();
}
+ return nativeGetClasses(nativeMapViewPtr);
+ }
- public List<String> getClasses() {
- return nativeGetClasses(nativeMapViewPtr);
+ public void setStyleUrl(String url) {
+ if (isDestroyedOn("setStyleUrl")) {
+ return;
}
+ nativeSetStyleUrl(nativeMapViewPtr, url);
+ }
- public void setStyleUrl(String url) {
- nativeSetStyleUrl(nativeMapViewPtr, url);
+ public String getStyleUrl() {
+ if (isDestroyedOn("getStyleUrl")) {
+ return null;
}
+ return nativeGetStyleUrl(nativeMapViewPtr);
+ }
- public void setStyleJson(String newStyleJson) {
- nativeSetStyleJson(nativeMapViewPtr, newStyleJson);
+ public void setStyleJson(String newStyleJson) {
+ if (isDestroyedOn("setStyleJson")) {
+ return;
}
+ nativeSetStyleJson(nativeMapViewPtr, newStyleJson);
+ }
- public String getStyleJson() {
- return nativeGetStyleJson(nativeMapViewPtr);
+ public String getStyleJson() {
+ if (isDestroyedOn("getStyleJson")) {
+ return null;
}
+ return nativeGetStyleJson(nativeMapViewPtr);
+ }
- public void setAccessToken(String accessToken) {
- nativeSetAccessToken(nativeMapViewPtr, accessToken);
+ public void setAccessToken(String accessToken) {
+ if (isDestroyedOn("setAccessToken")) {
+ return;
}
+ nativeSetAccessToken(nativeMapViewPtr, accessToken);
+ }
- public String getAccessToken() {
- return nativeGetAccessToken(nativeMapViewPtr);
+ public String getAccessToken() {
+ if (isDestroyedOn("getAccessToken")) {
+ return null;
}
+ return nativeGetAccessToken(nativeMapViewPtr);
+ }
- public void cancelTransitions() {
- nativeCancelTransitions(nativeMapViewPtr);
+ public void cancelTransitions() {
+ if (isDestroyedOn("cancelTransitions")) {
+ return;
}
+ nativeCancelTransitions(nativeMapViewPtr);
+ }
- public void setGestureInProgress(boolean inProgress) {
- nativeSetGestureInProgress(nativeMapViewPtr, inProgress);
+ public void setGestureInProgress(boolean inProgress) {
+ if (isDestroyedOn("setGestureInProgress")) {
+ return;
}
+ nativeSetGestureInProgress(nativeMapViewPtr, inProgress);
+ }
- public void moveBy(double dx, double dy) {
- moveBy(dx, dy, 0);
+ public void moveBy(double dx, double dy) {
+ if (isDestroyedOn("moveBy")) {
+ return;
}
+ moveBy(dx, dy, 0);
+ }
- public void moveBy(double dx, double dy, long duration) {
- nativeMoveBy(nativeMapViewPtr, dx, dy, duration);
+ public void moveBy(double dx, double dy, long duration) {
+ if (isDestroyedOn("moveBy")) {
+ return;
}
+ nativeMoveBy(nativeMapViewPtr, dx / pixelRatio, dy / pixelRatio, duration);
+ }
- public void setLatLng(LatLng latLng) {
- setLatLng(latLng, 0);
+ public void setLatLng(LatLng latLng) {
+ if (isDestroyedOn("setLatLng")) {
+ return;
}
+ setLatLng(latLng, 0);
+ }
- public void setLatLng(LatLng latLng, long duration) {
- nativeSetLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude(), duration);
+ public void setLatLng(LatLng latLng, long duration) {
+ if (isDestroyedOn("setLatLng")) {
+ return;
}
+ nativeSetLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude(), duration);
+ }
- public LatLng getLatLng() {
- return nativeGetLatLng(nativeMapViewPtr);
+ public LatLng getLatLng() {
+ if (isDestroyedOn("")) {
+ return new LatLng();
}
+ return nativeGetLatLng(nativeMapViewPtr);
+ }
- public void resetPosition() {
- nativeResetPosition(nativeMapViewPtr);
+ public void resetPosition() {
+ if (isDestroyedOn("resetPosition")) {
+ return;
}
+ nativeResetPosition(nativeMapViewPtr);
+ }
- public double getPitch() {
- return nativeGetPitch(nativeMapViewPtr);
+ public double getPitch() {
+ if (isDestroyedOn("getPitch")) {
+ return 0;
}
+ return nativeGetPitch(nativeMapViewPtr);
+ }
- public void setPitch(double pitch, long duration) {
- nativeSetPitch(nativeMapViewPtr, pitch, duration);
+ public void setPitch(double pitch, long duration) {
+ if (isDestroyedOn("setPitch")) {
+ return;
}
+ nativeSetPitch(nativeMapViewPtr, pitch, duration);
+ }
- public void scaleBy(double ds) {
- scaleBy(ds, Double.NaN, Double.NaN);
+ public void scaleBy(double ds) {
+ if (isDestroyedOn("scaleBy")) {
+ return;
}
+ scaleBy(ds, Double.NaN, Double.NaN);
+ }
- public void scaleBy(double ds, double cx, double cy) {
- scaleBy(ds, cx, cy, 0);
+ public void scaleBy(double ds, double cx, double cy) {
+ if (isDestroyedOn("scaleBy")) {
+ return;
}
+ scaleBy(ds, cx, cy, 0);
+ }
- public void scaleBy(double ds, double cx, double cy, long duration) {
- nativeScaleBy(nativeMapViewPtr, ds, cx, cy, duration);
+ public void scaleBy(double ds, double cx, double cy, long duration) {
+ if (isDestroyedOn("scaleBy")) {
+ return;
}
+ nativeScaleBy(nativeMapViewPtr, ds, cx / pixelRatio, cy / pixelRatio, duration);
+ }
- public void setScale(double scale) {
- setScale(scale, Double.NaN, Double.NaN);
+ public void setScale(double scale) {
+ if (isDestroyedOn("setScale")) {
+ return;
}
+ setScale(scale, Double.NaN, Double.NaN);
+ }
- public void setScale(double scale, double cx, double cy) {
- setScale(scale, cx, cy, 0);
+ public void setScale(double scale, double cx, double cy) {
+ if (isDestroyedOn("setScale")) {
+ return;
}
+ setScale(scale, cx, cy, 0);
+ }
- public void setScale(double scale, double cx, double cy, long duration) {
- nativeSetScale(nativeMapViewPtr, scale, cx, cy, duration);
+ public void setScale(double scale, double cx, double cy, long duration) {
+ if (isDestroyedOn("setScale")) {
+ return;
}
+ nativeSetScale(nativeMapViewPtr, scale, cx / pixelRatio, cy / pixelRatio, duration);
+ }
- public double getScale() {
- return nativeGetScale(nativeMapViewPtr);
+ public double getScale() {
+ if (isDestroyedOn("getScale")) {
+ return 0;
}
+ return nativeGetScale(nativeMapViewPtr);
+ }
- public void setZoom(double zoom) {
- setZoom(zoom, 0);
+ public void setZoom(double zoom) {
+ if (isDestroyedOn("setZoom")) {
+ return;
}
+ setZoom(zoom, 0);
+ }
- public void setZoom(double zoom, long duration) {
- nativeSetZoom(nativeMapViewPtr, zoom, duration);
+ public void setZoom(double zoom, long duration) {
+ if (isDestroyedOn("setZoom")) {
+ return;
}
+ nativeSetZoom(nativeMapViewPtr, zoom, duration);
+ }
- public double getZoom() {
- return nativeGetZoom(nativeMapViewPtr);
+ public double getZoom() {
+ if (isDestroyedOn("getZoom")) {
+ return 0;
}
+ return nativeGetZoom(nativeMapViewPtr);
+ }
- public void resetZoom() {
- nativeResetZoom(nativeMapViewPtr);
+ public void resetZoom() {
+ if (isDestroyedOn("resetZoom")) {
+ return;
}
+ nativeResetZoom(nativeMapViewPtr);
+ }
- public void setMinZoom(double zoom) {
- nativeSetMinZoom(nativeMapViewPtr, zoom);
+ public void setMinZoom(double zoom) {
+ if (isDestroyedOn("setMinZoom")) {
+ return;
}
+ nativeSetMinZoom(nativeMapViewPtr, zoom);
+ }
- public double getMinZoom() {
- return nativeGetMinZoom(nativeMapViewPtr);
+ public double getMinZoom() {
+ if (isDestroyedOn("getMinZoom")) {
+ return 0;
}
+ return nativeGetMinZoom(nativeMapViewPtr);
+ }
- public void setMaxZoom(double zoom) {
- nativeSetMaxZoom(nativeMapViewPtr, zoom);
+ public void setMaxZoom(double zoom) {
+ if (isDestroyedOn("setMaxZoom")) {
+ return;
}
+ nativeSetMaxZoom(nativeMapViewPtr, zoom);
+ }
- public double getMaxZoom() {
- return nativeGetMaxZoom(nativeMapViewPtr);
+ public double getMaxZoom() {
+ if (isDestroyedOn("getMaxZoom")) {
+ return 0;
}
+ return nativeGetMaxZoom(nativeMapViewPtr);
+ }
- public void rotateBy(double sx, double sy, double ex, double ey) {
- rotateBy(sx, sy, ex, ey, 0);
+ public void rotateBy(double sx, double sy, double ex, double ey) {
+ if (isDestroyedOn("rotateBy")) {
+ return;
}
+ rotateBy(sx, sy, ex, ey, 0);
+ }
- public void rotateBy(double sx, double sy, double ex, double ey,
- long duration) {
- nativeRotateBy(nativeMapViewPtr, sx, sy, ex, ey, duration);
+ public void rotateBy(double sx, double sy, double ex, double ey,
+ long duration) {
+ if (isDestroyedOn("rotateBy")) {
+ return;
}
+ nativeRotateBy(nativeMapViewPtr, sx / pixelRatio, sy / pixelRatio, ex, ey, duration);
+ }
- public void setContentPadding(double top, double left, double bottom, double right) {
- nativeSetContentPadding(nativeMapViewPtr, top, left, bottom, right);
+ public void setContentPadding(int[] padding) {
+ if (isDestroyedOn("setContentPadding")) {
+ return;
}
+ nativeSetContentPadding(nativeMapViewPtr,
+ padding[1] / pixelRatio,
+ padding[0] / pixelRatio,
+ padding[3] / pixelRatio,
+ padding[2] / pixelRatio);
+ }
- public void setBearing(double degrees) {
- setBearing(degrees, 0);
+ public void setBearing(double degrees) {
+ if (isDestroyedOn("setBearing")) {
+ return;
}
+ setBearing(degrees, 0);
+ }
- public void setBearing(double degrees, long duration) {
- nativeSetBearing(nativeMapViewPtr, degrees, duration);
+ public void setBearing(double degrees, long duration) {
+ if (isDestroyedOn("setBearing")) {
+ return;
}
+ nativeSetBearing(nativeMapViewPtr, degrees, duration);
+ }
- public void setBearing(double degrees, double cx, double cy) {
- nativeSetBearingXY(nativeMapViewPtr, degrees, cx, cy);
+ public void setBearing(double degrees, double cx, double cy) {
+ if (isDestroyedOn("setBearing")) {
+ return;
}
+ nativeSetBearingXY(nativeMapViewPtr, degrees, cx / pixelRatio, cy / pixelRatio);
+ }
- public double getBearing() {
- return nativeGetBearing(nativeMapViewPtr);
+ public double getBearing() {
+ if (isDestroyedOn("getBearing")) {
+ return 0;
}
+ return nativeGetBearing(nativeMapViewPtr);
+ }
- public void resetNorth() {
- nativeResetNorth(nativeMapViewPtr);
+ public void resetNorth() {
+ if (isDestroyedOn("resetNorth")) {
+ return;
}
+ nativeResetNorth(nativeMapViewPtr);
+ }
- public long addMarker(Marker marker) {
- Marker[] markers = {marker};
- return nativeAddMarkers(nativeMapViewPtr, markers)[0];
+ public long addMarker(Marker marker) {
+ if (isDestroyedOn("addMarker")) {
+ return 0;
}
+ Marker[] markers = {marker};
+ return nativeAddMarkers(nativeMapViewPtr, markers)[0];
+ }
- public long[] addMarkers(List<Marker> markers) {
- return nativeAddMarkers(nativeMapViewPtr, markers.toArray(new Marker[markers.size()]));
+ public long[] addMarkers(List<Marker> markers) {
+ if (isDestroyedOn("addMarkers")) {
+ return new long[] {};
}
+ return nativeAddMarkers(nativeMapViewPtr, markers.toArray(new Marker[markers.size()]));
+ }
- public long addPolyline(Polyline polyline) {
- Polyline[] polylines = {polyline};
- return nativeAddPolylines(nativeMapViewPtr, polylines)[0];
+ public long addPolyline(Polyline polyline) {
+ if (isDestroyedOn("addPolyline")) {
+ return 0;
}
+ Polyline[] polylines = {polyline};
+ return nativeAddPolylines(nativeMapViewPtr, polylines)[0];
+ }
- public long[] addPolylines(List<Polyline> polylines) {
- return nativeAddPolylines(nativeMapViewPtr, polylines.toArray(new Polyline[polylines.size()]));
+ public long[] addPolylines(List<Polyline> polylines) {
+ if (isDestroyedOn("addPolylines")) {
+ return new long[] {};
}
+ return nativeAddPolylines(nativeMapViewPtr, polylines.toArray(new Polyline[polylines.size()]));
+ }
- public long addPolygon(Polygon polygon) {
- Polygon[] polygons = {polygon};
- return nativeAddPolygons(nativeMapViewPtr, polygons)[0];
+ public long addPolygon(Polygon polygon) {
+ if (isDestroyedOn("addPolygon")) {
+ return 0;
}
+ Polygon[] polygons = {polygon};
+ return nativeAddPolygons(nativeMapViewPtr, polygons)[0];
+ }
- public long[] addPolygons(List<Polygon> polygons) {
- return nativeAddPolygons(nativeMapViewPtr, polygons.toArray(new Polygon[polygons.size()]));
+ public long[] addPolygons(List<Polygon> polygons) {
+ if (isDestroyedOn("addPolygons")) {
+ return new long[] {};
}
+ return nativeAddPolygons(nativeMapViewPtr, polygons.toArray(new Polygon[polygons.size()]));
+ }
- public void updateMarker(Marker marker) {
- LatLng position = marker.getPosition();
- Icon icon = marker.getIcon();
- nativeUpdateMarker(nativeMapViewPtr, marker.getId(), position.getLatitude(), position.getLongitude(), icon.getId());
+ public void updateMarker(Marker marker) {
+ if (isDestroyedOn("updateMarker")) {
+ return;
}
+ LatLng position = marker.getPosition();
+ Icon icon = marker.getIcon();
+ nativeUpdateMarker(nativeMapViewPtr, marker.getId(), position.getLatitude(), position.getLongitude(), icon.getId());
+ }
- public void updatePolygon(Polygon polygon) {
- nativeUpdatePolygon(nativeMapViewPtr, polygon.getId(), polygon);
+ public void updatePolygon(Polygon polygon) {
+ if (isDestroyedOn("updatePolygon")) {
+ return;
}
+ nativeUpdatePolygon(nativeMapViewPtr, polygon.getId(), polygon);
+ }
- public void updatePolyline(Polyline polyline) {
- nativeUpdatePolyline(nativeMapViewPtr, polyline.getId(), polyline);
+ public void updatePolyline(Polyline polyline) {
+ if (isDestroyedOn("updatePolyline")) {
+ return;
}
+ nativeUpdatePolyline(nativeMapViewPtr, polyline.getId(), polyline);
+ }
- public void removeAnnotation(long id) {
- long[] ids = {id};
- removeAnnotations(ids);
+ public void removeAnnotation(long id) {
+ if (isDestroyedOn("removeAnnotation")) {
+ return;
}
+ long[] ids = {id};
+ removeAnnotations(ids);
+ }
- public void removeAnnotations(long[] ids) {
- nativeRemoveAnnotations(nativeMapViewPtr, ids);
+ public void removeAnnotations(long[] ids) {
+ if (isDestroyedOn("removeAnnotations")) {
+ return;
}
+ nativeRemoveAnnotations(nativeMapViewPtr, ids);
+ }
- public long[] queryPointAnnotations(RectF rect) {
- return nativeQueryPointAnnotations(nativeMapViewPtr, rect);
+ public long[] queryPointAnnotations(RectF rect) {
+ if (isDestroyedOn("queryPointAnnotations")) {
+ return new long[] {};
}
+ return nativeQueryPointAnnotations(nativeMapViewPtr, rect);
+ }
- public void addAnnotationIcon(String symbol, int width, int height, float scale, byte[] pixels) {
- nativeAddAnnotationIcon(nativeMapViewPtr, symbol, width, height, scale, pixels);
+ public void addAnnotationIcon(String symbol, int width, int height, float scale, byte[] pixels) {
+ if (isDestroyedOn("addAnnotationIcon")) {
+ return;
}
+ nativeAddAnnotationIcon(nativeMapViewPtr, symbol, width, height, scale, pixels);
+ }
- public void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, double direction, long duration) {
- nativeSetVisibleCoordinateBounds(nativeMapViewPtr, coordinates, padding, direction, duration);
+ public void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, double direction, long duration) {
+ if (isDestroyedOn("setVisibleCoordinateBounds")) {
+ return;
}
+ nativeSetVisibleCoordinateBounds(nativeMapViewPtr, coordinates, padding, direction, duration);
+ }
- public void onLowMemory() {
- nativeOnLowMemory(nativeMapViewPtr);
+ public void onLowMemory() {
+ if (isDestroyedOn("onLowMemory")) {
+ return;
}
+ nativeOnLowMemory(nativeMapViewPtr);
+ }
- public void setDebug(boolean debug) {
- nativeSetDebug(nativeMapViewPtr, debug);
+ public void setDebug(boolean debug) {
+ if (isDestroyedOn("setDebug")) {
+ return;
}
+ nativeSetDebug(nativeMapViewPtr, debug);
+ }
- public void cycleDebugOptions() {
- nativeToggleDebug(nativeMapViewPtr);
+ public void cycleDebugOptions() {
+ if (isDestroyedOn("cycleDebugOptions")) {
+ return;
}
+ nativeToggleDebug(nativeMapViewPtr);
+ }
- public boolean getDebug() {
- return nativeGetDebug(nativeMapViewPtr);
+ public boolean getDebug() {
+ if (isDestroyedOn("getDebug")) {
+ return false;
}
+ return nativeGetDebug(nativeMapViewPtr);
+ }
- public boolean isFullyLoaded() {
- return nativeIsFullyLoaded(nativeMapViewPtr);
+ public boolean isFullyLoaded() {
+ if (isDestroyedOn("isFullyLoaded")) {
+ return false;
}
+ return nativeIsFullyLoaded(nativeMapViewPtr);
+ }
- public void setReachability(boolean status) {
- nativeSetReachability(nativeMapViewPtr, status);
+ public void setReachability(boolean status) {
+ if (isDestroyedOn("setReachability")) {
+ return;
}
+ nativeSetReachability(nativeMapViewPtr, status);
+ }
- public double getMetersPerPixelAtLatitude(double lat, double zoom) {
- return nativeGetMetersPerPixelAtLatitude(nativeMapViewPtr, lat, zoom);
+ public double getMetersPerPixelAtLatitude(double lat) {
+ if (isDestroyedOn("getMetersPerPixelAtLatitude")) {
+ return 0;
}
+ return nativeGetMetersPerPixelAtLatitude(nativeMapViewPtr, lat, getZoom());
+ }
- public ProjectedMeters projectedMetersForLatLng(LatLng latLng) {
- return nativeProjectedMetersForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude());
+ public ProjectedMeters projectedMetersForLatLng(LatLng latLng) {
+ if (isDestroyedOn("projectedMetersForLatLng")) {
+ return null;
}
+ return nativeProjectedMetersForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude());
+ }
- public LatLng latLngForProjectedMeters(ProjectedMeters projectedMeters) {
- return nativeLatLngForProjectedMeters(nativeMapViewPtr, projectedMeters.getNorthing(), projectedMeters.getEasting());
+ public LatLng latLngForProjectedMeters(ProjectedMeters projectedMeters) {
+ if (isDestroyedOn("latLngForProjectedMeters")) {
+ return new LatLng();
}
+ return nativeLatLngForProjectedMeters(nativeMapViewPtr, projectedMeters.getNorthing(),
+ projectedMeters.getEasting());
+ }
- public PointF pixelForLatLng(LatLng latLng) {
- return nativePixelForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude());
+ public PointF pixelForLatLng(LatLng latLng) {
+ if (isDestroyedOn("pixelForLatLng")) {
+ return new PointF();
}
+ PointF pointF = nativePixelForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude());
+ pointF.set(pointF.x * pixelRatio, pointF.y * pixelRatio);
+ return pointF;
+ }
- public LatLng latLngForPixel(PointF pixel) {
- return nativeLatLngForPixel(nativeMapViewPtr, pixel.x, pixel.y);
+ public LatLng latLngForPixel(PointF pixel) {
+ if (isDestroyedOn("latLngForPixel")) {
+ return new LatLng();
}
+ return nativeLatLngForPixel(nativeMapViewPtr, pixel.x / pixelRatio, pixel.y / pixelRatio);
+ }
- public double getTopOffsetPixelsForAnnotationSymbol(String symbolName) {
- return nativeGetTopOffsetPixelsForAnnotationSymbol(nativeMapViewPtr, symbolName);
+ public double getTopOffsetPixelsForAnnotationSymbol(String symbolName) {
+ if (isDestroyedOn("getTopOffsetPixelsForAnnotationSymbol")) {
+ return 0;
}
+ return nativeGetTopOffsetPixelsForAnnotationSymbol(nativeMapViewPtr, symbolName);
+ }
- public void jumpTo(double angle, LatLng center, double pitch, double zoom) {
- nativeJumpTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), pitch, zoom);
+ public void jumpTo(double angle, LatLng center, double pitch, double zoom) {
+ if (isDestroyedOn("jumpTo")) {
+ return;
}
+ nativeJumpTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), pitch, zoom);
+ }
- public void easeTo(double angle, LatLng center, long duration, double pitch, double zoom, boolean easingInterpolator) {
- nativeEaseTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom, easingInterpolator);
+ public void easeTo(double angle, LatLng center, long duration, double pitch, double zoom,
+ boolean easingInterpolator) {
+ if (isDestroyedOn("easeTo")) {
+ return;
}
+ nativeEaseTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom,
+ easingInterpolator);
+ }
- public void flyTo(double angle, LatLng center, long duration, double pitch, double zoom) {
- nativeFlyTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom);
+ public void flyTo(double angle, LatLng center, long duration, double pitch, double zoom) {
+ if (isDestroyedOn("flyTo")) {
+ return;
}
+ nativeFlyTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom);
+ }
- public double[] getCameraValues() {
- return nativeGetCameraValues(nativeMapViewPtr);
+ public double[] getCameraValues() {
+ if (isDestroyedOn("getCameraValues")) {
+ return new double[] {};
}
+ return nativeGetCameraValues(nativeMapViewPtr);
+ }
- // Runtime style Api
+ // Runtime style Api
- public Layer getLayer(String layerId) {
- return nativeGetLayer(nativeMapViewPtr, layerId);
+ public Layer getLayer(String layerId) {
+ if (isDestroyedOn("getLayer")) {
+ return null;
}
+ return nativeGetLayer(nativeMapViewPtr, layerId);
+ }
- public void addLayer(@NonNull Layer layer, @Nullable String before) {
- nativeAddLayer(nativeMapViewPtr, layer.getNativePtr(), before);
- layer.invalidate();
+ public void addLayer(@NonNull Layer layer, @Nullable String before) {
+ if (isDestroyedOn("")) {
+ return;
}
+ nativeAddLayer(nativeMapViewPtr, layer.getNativePtr(), before);
+ }
- public void removeLayer(@NonNull String layerId) throws NoSuchLayerException {
- nativeRemoveLayer(nativeMapViewPtr, layerId);
+ public void removeLayer(@NonNull String layerId) throws NoSuchLayerException {
+ if (isDestroyedOn("removeLayer")) {
+ return;
}
+ nativeRemoveLayerById(nativeMapViewPtr, layerId);
+ }
- public Source getSource(@NonNull String sourceId) {
- return nativeGetSource(nativeMapViewPtr, sourceId);
+ public void removeLayer(@NonNull Layer layer) throws NoSuchLayerException {
+ if (isDestroyedOn("removeLayer")) {
+ return;
}
+ nativeRemoveLayer(nativeMapViewPtr, layer.getNativePtr());
+ }
- public void addSource(@NonNull Source source) {
- nativeAddSource(nativeMapViewPtr, source.getNativePtr());
+ public Source getSource(@NonNull String sourceId) {
+ if (isDestroyedOn("getSource")) {
+ return null;
}
+ return nativeGetSource(nativeMapViewPtr, sourceId);
+ }
- public void removeSource(@NonNull String sourceId) throws NoSuchSourceException {
- nativeRemoveSource(nativeMapViewPtr, sourceId);
+ public void addSource(@NonNull Source source) {
+ if (isDestroyedOn("addSource")) {
+ return;
}
+ nativeAddSource(nativeMapViewPtr, source.getNativePtr());
+ }
- public void addImage(@NonNull String name, @NonNull Bitmap image) {
- //Check/correct config
- if (image.getConfig() != Bitmap.Config.ARGB_8888) {
- image = image.copy(Bitmap.Config.ARGB_8888, false);
- }
-
- //Get pixels
- ByteBuffer buffer = ByteBuffer.allocate(image.getByteCount());
- image.copyPixelsToBuffer(buffer);
+ public void removeSource(@NonNull String sourceId) throws NoSuchSourceException {
+ if (isDestroyedOn("removeSource")) {
+ return;
+ }
+ nativeRemoveSourceById(nativeMapViewPtr, sourceId);
+ }
- //Determine pixel ratio
- float density = image.getDensity() == Bitmap.DENSITY_NONE ? Bitmap.DENSITY_NONE : image.getDensity();
- float pixelRatio = density / DisplayMetrics.DENSITY_DEFAULT;
+ public void removeSource(@NonNull Source source) throws NoSuchSourceException {
+ if (isDestroyedOn("removeSource")) {
+ return;
+ }
+ nativeRemoveSource(nativeMapViewPtr, source.getNativePtr());
+ }
- nativeAddImage(nativeMapViewPtr, name, image.getWidth(), image.getHeight(), pixelRatio, buffer.array());
+ public void addImage(@NonNull String name, @NonNull Bitmap image) {
+ if (isDestroyedOn("addImage")) {
+ return;
+ }
+ //Check/correct config
+ if (image.getConfig() != Bitmap.Config.ARGB_8888) {
+ image = image.copy(Bitmap.Config.ARGB_8888, false);
}
- public void removeImage(String name) {
- nativeRemoveImage(nativeMapViewPtr, name);
+ //Get pixels
+ ByteBuffer buffer = ByteBuffer.allocate(image.getByteCount());
+ image.copyPixelsToBuffer(buffer);
+
+ //Determine pixel ratio
+ float density = image.getDensity() == Bitmap.DENSITY_NONE ? Bitmap.DENSITY_NONE : image.getDensity();
+ float pixelRatio = density / DisplayMetrics.DENSITY_DEFAULT;
+
+ nativeAddImage(nativeMapViewPtr, name, image.getWidth(), image.getHeight(), pixelRatio, buffer.array());
+ }
+
+ public void removeImage(String name) {
+ if (isDestroyedOn("removeImage")) {
+ return;
}
+ nativeRemoveImage(nativeMapViewPtr, name);
+ }
- // Feature querying
+ // Feature querying
- @NonNull
- public List<Feature> queryRenderedFeatures(PointF coordinates, String... layerIds) {
- Feature[] features = nativeQueryRenderedFeaturesForPoint(nativeMapViewPtr, coordinates.x / pixelRatio, coordinates.y / pixelRatio, layerIds);
- return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
+ @NonNull
+ public List<Feature> queryRenderedFeatures(PointF coordinates, String... layerIds) {
+ if (isDestroyedOn("queryRenderedFeatures")) {
+ return new ArrayList<>();
}
+ Feature[] features = nativeQueryRenderedFeaturesForPoint(nativeMapViewPtr, coordinates.x / pixelRatio,
+ coordinates.y / pixelRatio, layerIds);
+ return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
+ }
- @NonNull
- public List<Feature> queryRenderedFeatures(RectF coordinates, String... layerIds) {
- Feature[] features = nativeQueryRenderedFeaturesForBox(
- nativeMapViewPtr,
- coordinates.left / pixelRatio,
- coordinates.top / pixelRatio,
- coordinates.right / pixelRatio,
- coordinates.bottom / pixelRatio,
- layerIds);
- return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
+ @NonNull
+ public List<Feature> queryRenderedFeatures(RectF coordinates, String... layerIds) {
+ if (isDestroyedOn("queryRenderedFeatures")) {
+ return new ArrayList<>();
}
+ Feature[] features = nativeQueryRenderedFeaturesForBox(
+ nativeMapViewPtr,
+ coordinates.left / pixelRatio,
+ coordinates.top / pixelRatio,
+ coordinates.right / pixelRatio,
+ coordinates.bottom / pixelRatio,
+ layerIds);
+ return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
+ }
- public void scheduleTakeSnapshot() {
- nativeScheduleTakeSnapshot(nativeMapViewPtr);
+ public void scheduleTakeSnapshot() {
+ if (isDestroyedOn("scheduleTakeSnapshot")) {
+ return;
}
+ nativeScheduleTakeSnapshot(nativeMapViewPtr);
+ }
- public void setApiBaseUrl(String baseUrl) {
- nativeSetAPIBaseURL(nativeMapViewPtr, baseUrl);
+ public void setApiBaseUrl(String baseUrl) {
+ if (isDestroyedOn("setApiBaseUrl")) {
+ return;
}
+ nativeSetAPIBaseURL(nativeMapViewPtr, baseUrl);
+ }
- //
- // Callbacks
- //
+ public float getPixelRatio() {
+ return pixelRatio;
+ }
- protected void onInvalidate() {
- mapView.onInvalidate();
- }
+ public Context getContext() {
+ return mapView.getContext();
+ }
- protected void onMapChanged(int rawChange) {
- mapView.onMapChanged(rawChange);
- }
+ //
+ // Callbacks
+ //
+
+ protected void onInvalidate() {
+ mapView.onInvalidate();
+ }
- protected void onFpsChanged(double fps) {
- mapView.onFpsChanged(fps);
+ protected void onMapChanged(int rawChange) {
+ if (onMapChangedListeners != null) {
+ for (MapView.OnMapChangedListener onMapChangedListener : onMapChangedListeners) {
+ onMapChangedListener.onMapChanged(rawChange);
+ }
}
+ }
- protected void onSnapshotReady(byte[] bytes) {
- mapView.onSnapshotReady(bytes);
+ protected void onFpsChanged(double fps) {
+ mapView.onFpsChanged(fps);
+ }
+
+ protected void onSnapshotReady(byte[] bytes) {
+ if (snapshotRequest != null && bytes != null) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inBitmap = snapshotRequest.getBitmap(); // the old Bitmap to be reused
+ options.inMutable = true;
+ options.inSampleSize = 1;
+ Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
+
+ MapboxMap.SnapshotReadyCallback callback = snapshotRequest.getCallback();
+ if (callback != null) {
+ callback.onSnapshotReady(bitmap);
+ }
}
+ }
+
+ //
+ // JNI methods
+ //
- //
- // JNI methods
- //
+ private native long nativeCreate(String cachePath, String dataPath, String apkPath, float pixelRatio,
+ int availableProcessors, long totalMemory);
- private native long nativeCreate(String cachePath, String dataPath, String apkPath, float pixelRatio, int availableProcessors, long totalMemory);
+ private native void nativeDestroy(long nativeMapViewPtr);
- private native void nativeDestroy(long nativeMapViewPtr);
+ private native void nativeInitializeDisplay(long nativeMapViewPtr);
- private native void nativeInitializeDisplay(long nativeMapViewPtr);
+ private native void nativeTerminateDisplay(long nativeMapViewPtr);
- private native void nativeTerminateDisplay(long nativeMapViewPtr);
+ private native void nativeInitializeContext(long nativeMapViewPtr);
- private native void nativeInitializeContext(long nativeMapViewPtr);
+ private native void nativeTerminateContext(long nativeMapViewPtr);
- private native void nativeTerminateContext(long nativeMapViewPtr);
+ private native void nativeCreateSurface(long nativeMapViewPtr,
+ Surface surface);
- private native void nativeCreateSurface(long nativeMapViewPtr,
- Surface surface);
+ private native void nativeDestroySurface(long nativeMapViewPtr);
- private native void nativeDestroySurface(long nativeMapViewPtr);
+ private native void nativeUpdate(long nativeMapViewPtr);
- private native void nativeUpdate(long nativeMapViewPtr);
+ private native void nativeRender(long nativeMapViewPtr);
- private native void nativeRender(long nativeMapViewPtr);
+ private native void nativeViewResize(long nativeMapViewPtr, int width, int height);
- private native void nativeViewResize(long nativeMapViewPtr, int width, int height);
+ private native void nativeFramebufferResize(long nativeMapViewPtr, int fbWidth, int fbHeight);
- private native void nativeFramebufferResize(long nativeMapViewPtr, int fbWidth, int fbHeight);
+ private native void nativeAddClass(long nativeMapViewPtr, String clazz);
- private native void nativeAddClass(long nativeMapViewPtr, String clazz);
+ private native void nativeRemoveClass(long nativeMapViewPtr, String clazz);
- private native void nativeRemoveClass(long nativeMapViewPtr, String clazz);
+ private native boolean nativeHasClass(long nativeMapViewPtr, String clazz);
- private native boolean nativeHasClass(long nativeMapViewPtr, String clazz);
+ private native void nativeSetClasses(long nativeMapViewPtr,
+ List<String> classes);
- private native void nativeSetClasses(long nativeMapViewPtr,
- List<String> classes);
+ private native List<String> nativeGetClasses(long nativeMapViewPtr);
- private native List<String> nativeGetClasses(long nativeMapViewPtr);
+ private native void nativeSetStyleUrl(long nativeMapViewPtr, String url);
- private native void nativeSetStyleUrl(long nativeMapViewPtr, String url);
+ private native String nativeGetStyleUrl(long nativeMapViewPtr);
- private native void nativeSetStyleJson(long nativeMapViewPtr, String newStyleJson);
+ private native void nativeSetStyleJson(long nativeMapViewPtr, String newStyleJson);
- private native String nativeGetStyleJson(long nativeMapViewPtr);
+ private native String nativeGetStyleJson(long nativeMapViewPtr);
- private native void nativeSetAccessToken(long nativeMapViewPtr, String accessToken);
+ private native void nativeSetAccessToken(long nativeMapViewPtr, String accessToken);
- private native String nativeGetAccessToken(long nativeMapViewPtr);
+ private native String nativeGetAccessToken(long nativeMapViewPtr);
- private native void nativeCancelTransitions(long nativeMapViewPtr);
+ private native void nativeCancelTransitions(long nativeMapViewPtr);
- private native void nativeSetGestureInProgress(long nativeMapViewPtr, boolean inProgress);
+ private native void nativeSetGestureInProgress(long nativeMapViewPtr, boolean inProgress);
- private native void nativeMoveBy(long nativeMapViewPtr, double dx,
- double dy, long duration);
+ private native void nativeMoveBy(long nativeMapViewPtr, double dx,
+ double dy, long duration);
- private native void nativeSetLatLng(long nativeMapViewPtr, double latitude, double longitude,
- long duration);
+ private native void nativeSetLatLng(long nativeMapViewPtr, double latitude, double longitude,
+ long duration);
- private native LatLng nativeGetLatLng(long nativeMapViewPtr);
+ private native LatLng nativeGetLatLng(long nativeMapViewPtr);
- private native void nativeResetPosition(long nativeMapViewPtr);
+ private native void nativeResetPosition(long nativeMapViewPtr);
- private native double nativeGetPitch(long nativeMapViewPtr);
+ private native double nativeGetPitch(long nativeMapViewPtr);
- private native void nativeSetPitch(long nativeMapViewPtr, double pitch, long duration);
+ private native void nativeSetPitch(long nativeMapViewPtr, double pitch, long duration);
- private native void nativeScaleBy(long nativeMapViewPtr, double ds,
- double cx, double cy, long duration);
+ private native void nativeScaleBy(long nativeMapViewPtr, double ds,
+ double cx, double cy, long duration);
- private native void nativeSetScale(long nativeMapViewPtr, double scale,
- double cx, double cy, long duration);
+ private native void nativeSetScale(long nativeMapViewPtr, double scale,
+ double cx, double cy, long duration);
- private native double nativeGetScale(long nativeMapViewPtr);
+ private native double nativeGetScale(long nativeMapViewPtr);
- private native void nativeSetZoom(long nativeMapViewPtr, double zoom,
- long duration);
+ private native void nativeSetZoom(long nativeMapViewPtr, double zoom,
+ long duration);
+
+ private native double nativeGetZoom(long nativeMapViewPtr);
- private native double nativeGetZoom(long nativeMapViewPtr);
+ private native void nativeResetZoom(long nativeMapViewPtr);
- private native void nativeResetZoom(long nativeMapViewPtr);
+ private native void nativeSetMinZoom(long nativeMapViewPtr, double zoom);
- private native void nativeSetMinZoom(long nativeMapViewPtr, double zoom);
+ private native double nativeGetMinZoom(long nativeMapViewPtr);
- private native double nativeGetMinZoom(long nativeMapViewPtr);
+ private native void nativeSetMaxZoom(long nativeMapViewPtr, double zoom);
- private native void nativeSetMaxZoom(long nativeMapViewPtr, double zoom);
+ private native double nativeGetMaxZoom(long nativeMapViewPtr);
- private native double nativeGetMaxZoom(long nativeMapViewPtr);
+ private native void nativeRotateBy(long nativeMapViewPtr, double sx,
+ double sy, double ex, double ey, long duration);
- private native void nativeRotateBy(long nativeMapViewPtr, double sx,
- double sy, double ex, double ey, long duration);
+ private native void nativeSetContentPadding(long nativeMapViewPtr, double top, double left, double bottom,
+ double right);
- private native void nativeSetContentPadding(long nativeMapViewPtr, double top, double left, double bottom, double right);
+ private native void nativeSetBearing(long nativeMapViewPtr, double degrees,
+ long duration);
- private native void nativeSetBearing(long nativeMapViewPtr, double degrees,
- long duration);
+ private native void nativeSetBearingXY(long nativeMapViewPtr, double degrees,
+ double cx, double cy);
- private native void nativeSetBearingXY(long nativeMapViewPtr, double degrees,
- double cx, double cy);
+ private native double nativeGetBearing(long nativeMapViewPtr);
- private native double nativeGetBearing(long nativeMapViewPtr);
+ private native void nativeResetNorth(long nativeMapViewPtr);
- private native void nativeResetNorth(long nativeMapViewPtr);
+ private native void nativeUpdateMarker(long nativeMapViewPtr, long markerId, double lat, double lon, String iconId);
- private native void nativeUpdateMarker(long nativeMapViewPtr, long markerId, double lat, double lon, String iconId);
+ private native long[] nativeAddMarkers(long nativeMapViewPtr, Marker[] markers);
- private native long[] nativeAddMarkers(long nativeMapViewPtr, Marker[] markers);
+ private native long[] nativeAddPolylines(long nativeMapViewPtr, Polyline[] polylines);
- private native long[] nativeAddPolylines(long nativeMapViewPtr, Polyline[] polylines);
+ private native long[] nativeAddPolygons(long nativeMapViewPtr, Polygon[] polygons);
- private native long[] nativeAddPolygons(long nativeMapViewPtr, Polygon[] polygons);
+ private native void nativeRemoveAnnotations(long nativeMapViewPtr, long[] id);
- private native void nativeRemoveAnnotations(long nativeMapViewPtr, long[] id);
+ private native long[] nativeQueryPointAnnotations(long nativeMapViewPtr, RectF rect);
- private native long[] nativeQueryPointAnnotations(long nativeMapViewPtr, RectF rect);
+ private native void nativeAddAnnotationIcon(long nativeMapViewPtr, String symbol,
+ int width, int height, float scale, byte[] pixels);
- private native void nativeAddAnnotationIcon(long nativeMapViewPtr, String symbol,
- int width, int height, float scale, byte[] pixels);
+ private native void nativeSetVisibleCoordinateBounds(long nativeMapViewPtr, LatLng[] coordinates,
+ RectF padding, double direction, long duration);
- private native void nativeSetVisibleCoordinateBounds(long nativeMapViewPtr, LatLng[] coordinates,
- RectF padding, double direction, long duration);
+ private native void nativeOnLowMemory(long nativeMapViewPtr);
- private native void nativeOnLowMemory(long nativeMapViewPtr);
+ private native void nativeSetDebug(long nativeMapViewPtr, boolean debug);
- private native void nativeSetDebug(long nativeMapViewPtr, boolean debug);
+ private native void nativeToggleDebug(long nativeMapViewPtr);
- private native void nativeToggleDebug(long nativeMapViewPtr);
+ private native boolean nativeGetDebug(long nativeMapViewPtr);
- private native boolean nativeGetDebug(long nativeMapViewPtr);
+ private native boolean nativeIsFullyLoaded(long nativeMapViewPtr);
- private native boolean nativeIsFullyLoaded(long nativeMapViewPtr);
+ private native void nativeSetReachability(long nativeMapViewPtr, boolean status);
- private native void nativeSetReachability(long nativeMapViewPtr, boolean status);
+ private native double nativeGetMetersPerPixelAtLatitude(long nativeMapViewPtr, double lat, double zoom);
- private native double nativeGetMetersPerPixelAtLatitude(long nativeMapViewPtr, double lat, double zoom);
+ private native ProjectedMeters nativeProjectedMetersForLatLng(long nativeMapViewPtr, double latitude,
+ double longitude);
- private native ProjectedMeters nativeProjectedMetersForLatLng(long nativeMapViewPtr, double latitude, double longitude);
+ private native LatLng nativeLatLngForProjectedMeters(long nativeMapViewPtr, double northing, double easting);
- private native LatLng nativeLatLngForProjectedMeters(long nativeMapViewPtr, double northing, double easting);
+ private native PointF nativePixelForLatLng(long nativeMapViewPtr, double lat, double lon);
- private native PointF nativePixelForLatLng(long nativeMapViewPtr, double lat, double lon);
+ private native LatLng nativeLatLngForPixel(long nativeMapViewPtr, float x, float y);
- private native LatLng nativeLatLngForPixel(long nativeMapViewPtr, float x, float y);
+ private native double nativeGetTopOffsetPixelsForAnnotationSymbol(long nativeMapViewPtr, String symbolName);
- private native double nativeGetTopOffsetPixelsForAnnotationSymbol(long nativeMapViewPtr, String symbolName);
+ private native void nativeJumpTo(long nativeMapViewPtr, double angle, double latitude, double longitude,
+ double pitch, double zoom);
- private native void nativeJumpTo(long nativeMapViewPtr, double angle, double latitude, double longitude, double pitch, double zoom);
+ private native void nativeEaseTo(long nativeMapViewPtr, double angle, double latitude, double longitude,
+ long duration, double pitch, double zoom, boolean easingInterpolator);
- private native void nativeEaseTo(long nativeMapViewPtr, double angle, double latitude, double longitude, long duration, double pitch, double zoom, boolean easingInterpolator);
+ private native void nativeFlyTo(long nativeMapViewPtr, double angle, double latitude, double longitude,
+ long duration, double pitch, double zoom);
- private native void nativeFlyTo(long nativeMapViewPtr, double angle, double latitude, double longitude, long duration, double pitch, double zoom);
+ private native double[] nativeGetCameraValues(long nativeMapViewPtr);
- private native double[] nativeGetCameraValues(long nativeMapViewPtr);
+ private native Layer nativeGetLayer(long nativeMapViewPtr, String layerId);
- private native Layer nativeGetLayer(long nativeMapViewPtr, String layerId);
+ private native void nativeAddLayer(long nativeMapViewPtr, long layerPtr, String before);
- private native void nativeAddLayer(long nativeMapViewPtr, long layerPtr, String before);
+ private native void nativeRemoveLayerById(long nativeMapViewPtr, String layerId) throws NoSuchLayerException;
- private native void nativeRemoveLayer(long nativeMapViewPtr, String layerId) throws NoSuchLayerException;
+ private native void nativeRemoveLayer(long nativeMapViewPtr, long layerId) throws NoSuchLayerException;
- private native Source nativeGetSource(long nativeMapViewPtr, String sourceId);
+ private native Source nativeGetSource(long nativeMapViewPtr, String sourceId);
- private native void nativeAddSource(long nativeMapViewPtr, long nativeSourcePtr);
+ private native void nativeAddSource(long nativeMapViewPtr, long nativeSourcePtr);
- private native void nativeRemoveSource(long nativeMapViewPtr, String sourceId) throws NoSuchSourceException;
+ private native void nativeRemoveSourceById(long nativeMapViewPtr, String sourceId) throws NoSuchSourceException;
- private native void nativeAddImage(long nativeMapViewPtr, String name, int width, int height, float pixelRatio, byte[] array);
+ private native void nativeRemoveSource(long nativeMapViewPtr, long sourcePtr) throws NoSuchSourceException;
- private native void nativeRemoveImage(long nativeMapViewPtr, String name);
+ private native void nativeAddImage(long nativeMapViewPtr, String name, int width, int height, float pixelRatio,
+ byte[] array);
- private native void nativeUpdatePolygon(long nativeMapViewPtr, long polygonId, Polygon polygon);
+ private native void nativeRemoveImage(long nativeMapViewPtr, String name);
- private native void nativeUpdatePolyline(long nativeMapviewPtr, long polylineId, Polyline polyline);
+ private native void nativeUpdatePolygon(long nativeMapViewPtr, long polygonId, Polygon polygon);
- private native void nativeScheduleTakeSnapshot(long nativeMapViewPtr);
+ private native void nativeUpdatePolyline(long nativeMapviewPtr, long polylineId, Polyline polyline);
- private native Feature[] nativeQueryRenderedFeaturesForPoint(long nativeMapViewPtr, float x, float y, String[] layerIds);
+ private native void nativeScheduleTakeSnapshot(long nativeMapViewPtr);
- private native Feature[] nativeQueryRenderedFeaturesForBox(long nativeMapViewPtr, float left, float top, float right, float bottom, String[] layerIds);
+ private native Feature[] nativeQueryRenderedFeaturesForPoint(long nativeMapViewPtr, float x, float y, String[]
+ layerIds);
+
+ private native Feature[] nativeQueryRenderedFeaturesForBox(long nativeMapViewPtr, float left, float top, float right,
+ float bottom, String[] layerIds);
+
+ private native void nativeSetAPIBaseURL(long nativeMapViewPtr, String baseUrl);
+
+ int getWidth() {
+ if (isDestroyedOn("")) {
+ return 0;
+ }
+ return mapView.getWidth();
+ }
+
+ int getHeight() {
+ if (isDestroyedOn("")) {
+ return 0;
+ }
+ return mapView.getHeight();
+ }
- private native void nativeSetAPIBaseURL(long nativeMapViewPtr, String baseUrl);
+ //
+ // MapChangeEvents
+ //
+
+ void addOnMapChangedListener(@NonNull MapView.OnMapChangedListener listener) {
+ onMapChangedListeners.add(listener);
+ }
+
+ void removeOnMapChangedListener(@NonNull MapView.OnMapChangedListener listener) {
+ onMapChangedListeners.remove(listener);
+ }
+
+ //
+ // Snapshot
+ //
+
+ void addSnapshotCallback(@NonNull MapboxMap.SnapshotReadyCallback callback, @Nullable Bitmap bitmap) {
+ snapshotRequest = new SnapshotRequest(bitmap, callback);
+ scheduleTakeSnapshot();
+ render();
+ }
+
+ private static class SnapshotRequest {
+ private Bitmap bitmap;
+ private MapboxMap.SnapshotReadyCallback callback;
+
+ SnapshotRequest(Bitmap bitmap, MapboxMap.SnapshotReadyCallback callback) {
+ this.bitmap = bitmap;
+ this.callback = callback;
+ }
+
+ public Bitmap getBitmap() {
+ return bitmap;
+ }
+
+ public MapboxMap.SnapshotReadyCallback getCallback() {
+ return callback;
+ }
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java
index 7ace9ec2d3..fc92e5028b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java
@@ -4,16 +4,17 @@ package com.mapbox.mapboxsdk.maps;
* Interface definition for a callback to be invoked when the map is ready to be used.
* <p>
* Once an instance of this interface is set on a {@link MapFragment} or {@link MapView} object,
- * the onMapReady(MapboxMap) method is triggered when the map is ready to be used and provides an instance of {@link MapboxMap}.
+ * the onMapReady(MapboxMap) method is triggered when the map is ready to be used and provides an instance of
+ * {@link MapboxMap}.
* </p>
*/
public interface OnMapReadyCallback {
- /**
- * Called when the map is ready to be used.
- *
- * @param mapboxMap An instance of MapboxMap associated with the {@link MapFragment} or
- * {@link MapView} that defines the callback.
- */
- void onMapReady(MapboxMap mapboxMap);
+ /**
+ * Called when the map is ready to be used.
+ *
+ * @param mapboxMap An instance of MapboxMap associated with the {@link MapFragment} or
+ * {@link MapView} that defines the callback.
+ */
+ void onMapReady(MapboxMap mapboxMap);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java
index e06ed38433..b7f93cc913 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java
@@ -15,93 +15,106 @@ import com.mapbox.mapboxsdk.geometry.VisibleRegion;
*/
public class Projection {
- private final MapView mapView;
- private final float screenDensity;
- private final PointF screenLocationPoint;
-
- Projection(@NonNull MapView mapView) {
- this.mapView = mapView;
- this.screenLocationPoint = new PointF();
- this.screenDensity = mapView.getContext() != null ? /* return default if unit test */
- mapView.getContext().getResources().getDisplayMetrics().density : 1.0f;
- }
-
- /**
- * <p>
- * Returns the distance spanned by one pixel at the specified latitude and current zoom level.
- * </p>
- * The distance between pixels decreases as the latitude approaches the poles.
- * This relationship parallels the relationship between longitudinal coordinates at different latitudes.
- *
- * @param latitude The latitude for which to return the value.
- * @return The distance measured in meters.
- */
- public double getMetersPerPixelAtLatitude(@FloatRange(from = -90, to = 90) double latitude) {
- return mapView.getMetersPerPixelAtLatitude(latitude);
- }
-
- /**
- * Returns the geographic location that corresponds to a screen location.
- * The screen location is specified in screen pixels (not display pixels) relative to the
- * top left of the map (not the top left of the whole screen).
- *
- * @param point A Point on the screen in screen pixels.
- * @return The LatLng corresponding to the point on the screen, or null if the ray through
- * the given screen point does not intersect the ground plane.
- */
- public LatLng fromScreenLocation(PointF point) {
- screenLocationPoint.set(point.x / screenDensity, point.y / screenDensity);
- return mapView.fromNativeScreenLocation(screenLocationPoint);
- }
-
- /**
- * Gets a projection of the viewing frustum for converting between screen coordinates and
- * geo-latitude/longitude coordinates.
- *
- * @return The projection of the viewing frustum in its current state.
- */
- public VisibleRegion getVisibleRegion() {
- LatLngBounds.Builder builder = new LatLngBounds.Builder();
-
- float left = mapView.getContentPaddingLeft();
- float right = mapView.getWidth() - mapView.getContentPaddingRight();
- float top = mapView.getContentPaddingTop();
- float bottom = mapView.getHeight() - mapView.getContentPaddingBottom();
-
- LatLng topLeft = fromScreenLocation(new PointF(left, top));
- LatLng topRight = fromScreenLocation(new PointF(right, top));
- LatLng bottomRight = fromScreenLocation(new PointF(right, bottom));
- LatLng bottomLeft = fromScreenLocation(new PointF(left, bottom));
-
- builder.include(topLeft)
- .include(topRight)
- .include(bottomRight)
- .include(bottomLeft);
-
- return new VisibleRegion(topLeft, topRight, bottomLeft, bottomRight, builder.build());
- }
-
- /**
- * Returns a screen location that corresponds to a geographical coordinate (LatLng).
- * The screen location is in screen pixels (not display pixels) relative to the top left
- * of the map (not of the whole screen).
- *
- * @param location A LatLng on the map to convert to a screen location.
- * @return A Point representing the screen location in screen pixels.
- */
- public PointF toScreenLocation(LatLng location) {
- PointF pointF = mapView.toNativeScreenLocation(location);
- pointF.set(pointF.x * screenDensity, pointF.y * screenDensity);
- return pointF;
- }
-
- /**
- * Calculates a zoom level based on minimum scale and current scale from MapView
- *
- * @param minScale The minimum scale to calculate the zoom level.
- * @return zoom level that fits the MapView.
- */
- public double calculateZoom(float minScale) {
- return Math.log(mapView.getScale() * minScale) / Math.log(2);
- }
+ private final NativeMapView nativeMapView;
+ private int[] contentPadding;
+
+ Projection(@NonNull NativeMapView nativeMapView) {
+ this.nativeMapView = nativeMapView;
+ this.contentPadding = new int[] {0, 0, 0, 0};
+ }
+
+ void setContentPadding(int[] contentPadding, int[] userLocationViewPadding) {
+ this.contentPadding = contentPadding;
+
+ int[] padding = new int[] {
+ contentPadding[0] + userLocationViewPadding[0],
+ contentPadding[1] + userLocationViewPadding[1],
+ contentPadding[2] + userLocationViewPadding[2],
+ contentPadding[3] + userLocationViewPadding[3]
+ };
+
+ nativeMapView.setContentPadding(padding);
+ }
+
+ int[] getContentPadding() {
+ return contentPadding;
+ }
+
+ public void invalidateContentPadding(int[] userLocationViewPadding) {
+ setContentPadding(contentPadding, userLocationViewPadding);
+ }
+
+ /**
+ * <p>
+ * Returns the distance spanned by one pixel at the specified latitude and current zoom level.
+ * </p>
+ * The distance between pixels decreases as the latitude approaches the poles.
+ * This relationship parallels the relationship between longitudinal coordinates at different latitudes.
+ *
+ * @param latitude The latitude for which to return the value.
+ * @return The distance measured in meters.
+ */
+ public double getMetersPerPixelAtLatitude(@FloatRange(from = -90, to = 90) double latitude) {
+ return nativeMapView.getMetersPerPixelAtLatitude(latitude);
+ }
+
+ /**
+ * Returns the geographic location that corresponds to a screen location.
+ * The screen location is specified in screen pixels (not display pixels) relative to the
+ * top left of the map (not the top left of the whole screen).
+ *
+ * @param point A Point on the screen in screen pixels.
+ * @return The LatLng corresponding to the point on the screen, or null if the ray through
+ * the given screen point does not intersect the ground plane.
+ */
+ public LatLng fromScreenLocation(PointF point) {
+ return nativeMapView.latLngForPixel(point);
+ }
+
+ /**
+ * Gets a projection of the viewing frustum for converting between screen coordinates and
+ * geo-latitude/longitude coordinates.
+ *
+ * @return The projection of the viewing frustum in its current state.
+ */
+ public VisibleRegion getVisibleRegion() {
+ LatLngBounds.Builder builder = new LatLngBounds.Builder();
+
+ float left = contentPadding[0];
+ float right = nativeMapView.getWidth() - contentPadding[2];
+ float top = contentPadding[1];
+ float bottom = nativeMapView.getHeight() - contentPadding[3];
+
+ LatLng topLeft = fromScreenLocation(new PointF(left, top));
+ LatLng topRight = fromScreenLocation(new PointF(right, top));
+ LatLng bottomRight = fromScreenLocation(new PointF(right, bottom));
+ LatLng bottomLeft = fromScreenLocation(new PointF(left, bottom));
+
+ builder.include(topLeft)
+ .include(topRight)
+ .include(bottomRight)
+ .include(bottomLeft);
+
+ return new VisibleRegion(topLeft, topRight, bottomLeft, bottomRight, builder.build());
+ }
+
+ /**
+ * Returns a screen location that corresponds to a geographical coordinate (LatLng).
+ * The screen location is in screen pixels (not display pixels) relative to the top left
+ * of the map (not of the whole screen).
+ *
+ * @param location A LatLng on the map to convert to a screen location.
+ * @return A Point representing the screen location in screen pixels.
+ */
+ public PointF toScreenLocation(LatLng location) {
+ return nativeMapView.pixelForLatLng(location);
+ }
+
+ float getHeight() {
+ return nativeMapView.getHeight();
+ }
+
+ float getWidth() {
+ return nativeMapView.getWidth();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java
index 72674c3bc9..90d933736b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java
@@ -1,23 +1,15 @@
package com.mapbox.mapboxsdk.maps;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
-import android.support.v4.content.ContextCompat;
-import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import com.mapbox.mapboxsdk.MapboxAccountManager;
-import com.mapbox.mapboxsdk.R;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
-import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException;
+import com.mapbox.mapboxsdk.utils.MapFragmentUtils;
/**
* Support Fragment wrapper around a map view.
@@ -35,202 +27,129 @@ import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException;
*/
public class SupportMapFragment extends Fragment {
- private MapView map;
- private OnMapReadyCallback onMapReadyCallback;
-
- /**
- * Creates a MapFragment instance
- *
- * @return MapFragment created
- */
- public static SupportMapFragment newInstance() {
- return new SupportMapFragment();
- }
-
- /**
- * Creates a MapFragment instance
- *
- * @param mapboxMapOptions The configuration options to be used.
- * @return MapFragment created.
- */
- public static SupportMapFragment newInstance(@Nullable MapboxMapOptions mapboxMapOptions) {
- SupportMapFragment mapFragment = new SupportMapFragment();
- Bundle bundle = new Bundle();
- bundle.putParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS, mapboxMapOptions);
- mapFragment.setArguments(bundle);
- return mapFragment;
- }
-
- /**
- * Creates the fragment view hierarchy.
- *
- * @param inflater Inflater used to inflate content.
- * @param container The parent layout for the map fragment.
- * @param savedInstanceState The saved instance state for the map fragment.
- * @return The view created
- */
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- super.onCreateView(inflater, container, savedInstanceState);
- Context context = inflater.getContext();
- MapboxMapOptions options = null;
-
- // Get bundle
- Bundle bundle = getArguments();
- if (bundle != null && bundle.containsKey(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS)) {
- options = bundle.getParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS);
- }
-
- // Assign an AccessToken if needed
- if (options == null || options.getAccessToken() == null) {
- String token = null;
- if (MapboxAccountManager.getInstance() != null) {
- token = MapboxAccountManager.getInstance().getAccessToken();
- } else {
- token = getToken(inflater.getContext());
- }
- if (TextUtils.isEmpty(token)) {
- throw new InvalidAccessTokenException();
- }
- if (options == null) {
- options = new MapboxMapOptions().accessToken(token);
- } else {
- options.accessToken(token);
- }
- }
-
- Drawable foregroundDrawable = options.getMyLocationForegroundDrawable();
- Drawable foregroundBearingDrawable = options.getMyLocationForegroundBearingDrawable();
- if (foregroundDrawable == null || foregroundBearingDrawable == null) {
- if (foregroundDrawable == null) {
- foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.ic_mylocationview_normal);
- }
- if (foregroundBearingDrawable == null) {
- foregroundBearingDrawable = ContextCompat.getDrawable(context, R.drawable.ic_mylocationview_bearing);
- }
- options.myLocationForegroundDrawables(foregroundDrawable, foregroundBearingDrawable);
- }
-
- if (options.getMyLocationBackgroundDrawable() == null) {
- options.myLocationBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.ic_mylocationview_background));
- }
-
- return map = new MapView(inflater.getContext(), options);
- }
-
- /**
- * <p>
- * Returns the Mapbox access token set in the app resources.
- * </p>
- * It will first search the application manifest for a {@link MapboxConstants#KEY_META_DATA_MANIFEST}
- * meta-data value. If not found it will then attempt to load the access token from the
- * {@code res/raw/token.txt} development file.
- *
- * @param context The {@link Context} of the {@link android.app.Activity} or {@link android.app.Fragment}.
- * @return The Mapbox access token or null if not found.
- * @see MapboxConstants#KEY_META_DATA_MANIFEST
- * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)}
- */
- @Deprecated
- private String getToken(@NonNull Context context) {
- try {
- // read out AndroidManifest
- PackageManager packageManager = context.getPackageManager();
- ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
- String token = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_MANIFEST);
- if (token == null || token.isEmpty()) {
- throw new IllegalArgumentException();
- }
- return token;
- } catch (Exception exception) {
- // use fallback on string resource, used for development
- int tokenResId = context.getResources().getIdentifier("mapbox_access_token", "string", context.getPackageName());
- return tokenResId != 0 ? context.getString(tokenResId) : null;
- }
- }
-
- /**
- * Called when the fragment view hierarchy is created.
- *
- * @param view The content view of the fragment
- * @param savedInstanceState THe saved instance state of the framgnt
- */
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- map.onCreate(savedInstanceState);
- }
-
- /**
- * Called when the fragment is visible for the users.
- */
- @Override
- public void onStart() {
- super.onStart();
- map.getMapAsync(onMapReadyCallback);
- }
-
- /**
- * Called when the fragment is ready to be interacted with.
- */
- @Override
- public void onResume() {
- super.onResume();
- map.onResume();
- }
-
- /**
- * Called when the fragment is pausing.
- */
- @Override
- public void onPause() {
- super.onPause();
- map.onPause();
- }
-
- /**
- * Called when the fragment state needs to be saved.
- *
- * @param outState The saved state
- */
- @Override
- public void onSaveInstanceState(@NonNull Bundle outState) {
- super.onSaveInstanceState(outState);
- map.onSaveInstanceState(outState);
- }
-
- /**
- * Called when the fragment is no longer visible for the user.
- */
- @Override
- public void onStop() {
- super.onStop();
- }
-
- /**
- * Called when the fragment receives onLowMemory call from the hosting Activity.
- */
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- map.onLowMemory();
- }
-
- /**
- * Called when the fragment is view hiearchy is being destroyed.
- */
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- map.onDestroy();
- }
-
- /**
- * Sets a callback object which will be triggered when the MapboxMap instance is ready to be used.
- *
- * @param onMapReadyCallback The callback to be invoked.
- */
- public void getMapAsync(@NonNull final OnMapReadyCallback onMapReadyCallback) {
- this.onMapReadyCallback = onMapReadyCallback;
- }
-}
+ private MapView map;
+ private OnMapReadyCallback onMapReadyCallback;
+
+ /**
+ * Creates a default MapFragment instance
+ *
+ * @return MapFragment created
+ */
+ public static SupportMapFragment newInstance() {
+ return new SupportMapFragment();
+ }
+
+ /**
+ * Creates a MapFragment instance
+ *
+ * @param mapboxMapOptions The configuration options to be used.
+ * @return MapFragment created.
+ */
+ public static SupportMapFragment newInstance(@Nullable MapboxMapOptions mapboxMapOptions) {
+ SupportMapFragment mapFragment = new SupportMapFragment();
+ mapFragment.setArguments(MapFragmentUtils.createFragmentArgs(mapboxMapOptions));
+ return mapFragment;
+ }
+
+ /**
+ * Creates the fragment view hierarchy.
+ *
+ * @param inflater Inflater used to inflate content.
+ * @param container The parent layout for the map fragment.
+ * @param savedInstanceState The saved instance state for the map fragment.
+ * @return The view created
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ super.onCreateView(inflater, container, savedInstanceState);
+ Context context = inflater.getContext();
+ return map = new MapView(context, MapFragmentUtils.resolveArgs(context, getArguments()));
+ }
+
+ /**
+ * Called when the fragment view hierarchy is created.
+ *
+ * @param view The content view of the fragment
+ * @param savedInstanceState THe saved instance state of the framgnt
+ */
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ map.onCreate(savedInstanceState);
+ }
+
+ /**
+ * Called when the fragment is visible for the users.
+ */
+ @Override
+ public void onStart() {
+ super.onStart();
+ map.onStart();
+ map.getMapAsync(onMapReadyCallback);
+ }
+
+ /**
+ * Called when the fragment is ready to be interacted with.
+ */
+ @Override
+ public void onResume() {
+ super.onResume();
+ map.onResume();
+ }
+
+ /**
+ * Called when the fragment is pausing.
+ */
+ @Override
+ public void onPause() {
+ super.onPause();
+ map.onPause();
+ }
+
+ /**
+ * Called when the fragment state needs to be saved.
+ *
+ * @param outState The saved state
+ */
+ @Override
+ public void onSaveInstanceState(@NonNull Bundle outState) {
+ super.onSaveInstanceState(outState);
+ map.onSaveInstanceState(outState);
+ }
+
+ /**
+ * Called when the fragment is no longer visible for the user.
+ */
+ @Override
+ public void onStop() {
+ super.onStop();
+ map.onStop();
+ }
+
+ /**
+ * Called when the fragment receives onLowMemory call from the hosting Activity.
+ */
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ map.onLowMemory();
+ }
+
+ /**
+ * Called when the fragment is view hiearchy is being destroyed.
+ */
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ map.onDestroy();
+ }
+
+ /**
+ * Sets a callback object which will be triggered when the MapboxMap instance is ready to be used.
+ *
+ * @param onMapReadyCallback The callback to be invoked.
+ */
+ public void getMapAsync(@NonNull final OnMapReadyCallback onMapReadyCallback) {
+ this.onMapReadyCallback = onMapReadyCallback;
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
index 474af19853..28591cf68c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
@@ -1,214 +1,368 @@
package com.mapbox.mapboxsdk.maps;
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.graphics.PointF;
+import android.location.Location;
+import android.os.Bundle;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
+import android.support.v4.content.ContextCompat;
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.constants.MyBearingTracking;
import com.mapbox.mapboxsdk.constants.MyLocationTracking;
+import com.mapbox.mapboxsdk.location.LocationListener;
+import com.mapbox.mapboxsdk.location.LocationServices;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
+import timber.log.Timber;
+
/**
* Settings for the user location and bearing tracking of a MapboxMap.
*/
-public class TrackingSettings {
+public final class TrackingSettings {
- private MapView mapView;
- private UiSettings uiSettings;
- private boolean dismissLocationTrackingOnGesture = true;
- private boolean dismissBearingTrackingOnGesture = true;
+ private final MyLocationView myLocationView;
+ private final UiSettings uiSettings;
+ private final FocalPointChangeListener focalPointChangedListener;
+ private LocationListener myLocationListener;
- @MyLocationTracking.Mode
- private int myLocationTrackingMode;
+ private boolean myLocationEnabled;
+ private boolean dismissLocationTrackingOnGesture = true;
+ private boolean dismissBearingTrackingOnGesture = true;
- @MyBearingTracking.Mode
- private int myBearingTrackingMode;
+ private MapboxMap.OnMyLocationTrackingModeChangeListener onMyLocationTrackingModeChangeListener;
+ private MapboxMap.OnMyBearingTrackingModeChangeListener onMyBearingTrackingModeChangeListener;
- TrackingSettings(@NonNull MapView mapView, UiSettings uiSettings) {
- this.mapView = mapView;
- this.uiSettings = uiSettings;
- }
+ TrackingSettings(@NonNull MyLocationView myLocationView, UiSettings uiSettings,
+ FocalPointChangeListener focalPointChangedListener) {
+ this.myLocationView = myLocationView;
+ this.focalPointChangedListener = focalPointChangedListener;
+ this.uiSettings = uiSettings;
+ }
- /**
- * <p>
- * Set the current my location tracking mode.
- * </p>
- * <p>
- * Will enable my location if not active.
- * </p>
- * See {@link MyLocationTracking} for different values.
- *
- * @param myLocationTrackingMode The location tracking mode to be used.
- * @throws SecurityException if no suitable permission is present
- * @see MyLocationTracking
- */
- @UiThread
- public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
- this.myLocationTrackingMode = myLocationTrackingMode;
- mapView.setMyLocationTrackingMode(myLocationTrackingMode);
- }
+ void initialise(MapboxMapOptions options) {
+ setMyLocationEnabled(options.getLocationEnabled());
+ }
- /**
- * Returns the current user location tracking mode.
- *
- * @return The current user location tracking mode.
- * One of the values from {@link MyLocationTracking.Mode}.
- * @see MyLocationTracking.Mode
- */
- @UiThread
- @MyLocationTracking.Mode
- public int getMyLocationTrackingMode() {
- return myLocationTrackingMode;
- }
+ void onSaveInstanceState(Bundle outState) {
+ outState.putInt(MapboxConstants.STATE_MY_LOCATION_TRACKING_MODE, getMyLocationTrackingMode());
+ outState.putInt(MapboxConstants.STATE_MY_BEARING_TRACKING_MODE, getMyBearingTrackingMode());
+ outState.putBoolean(MapboxConstants.STATE_MY_LOCATION_TRACKING_DISMISS, isDismissLocationTrackingOnGesture());
+ outState.putBoolean(MapboxConstants.STATE_MY_BEARING_TRACKING_DISMISS, isDismissBearingTrackingOnGesture());
+ outState.putBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED, isMyLocationEnabled());
+ }
- /**
- * <p>
- * Set the current my bearing tracking mode.
- * </p>
- * Shows the direction the user is heading.
- * <p>
- * When location tracking is disabled the direction of {@link MyLocationView} is rotated
- * When location tracking is enabled the {@link MapView} is rotated based on bearing value.
- * </p>
- * See {@link MyBearingTracking} for different values.
- *
- * @param myBearingTrackingMode The bearing tracking mode to be used.
- * @throws SecurityException if no suitable permission is present
- * @see MyBearingTracking
- */
- @UiThread
- public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) {
- this.myBearingTrackingMode = myBearingTrackingMode;
- mapView.setMyBearingTrackingMode(myBearingTrackingMode);
+ void onRestoreInstanceState(Bundle savedInstanceState) {
+ try {
+ setMyLocationEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED));
+ } catch (SecurityException ignore) {
+ // User did not accept location permissions
}
+ //noinspection ResourceType
+ setMyLocationTrackingMode(savedInstanceState.getInt(
+ MapboxConstants.STATE_MY_LOCATION_TRACKING_MODE, MyLocationTracking.TRACKING_NONE));
+ //noinspection ResourceType
+ setMyBearingTrackingMode(savedInstanceState.getInt(
+ MapboxConstants.STATE_MY_BEARING_TRACKING_MODE, MyBearingTracking.NONE));
+ setDismissLocationTrackingOnGesture(savedInstanceState.getBoolean(
+ MapboxConstants.STATE_MY_LOCATION_TRACKING_DISMISS, true));
+ setDismissBearingTrackingOnGesture(savedInstanceState.getBoolean(
+ MapboxConstants.STATE_MY_BEARING_TRACKING_DISMISS, true));
+ }
- /**
- * Returns the current user bearing tracking mode.
- * See {@link MyBearingTracking} for possible return values.
- *
- * @return the current user bearing tracking mode.
- * @see MyBearingTracking
- */
- @UiThread
- @MyBearingTracking.Mode
- public int getMyBearingTrackingMode() {
- return myBearingTrackingMode;
- }
+ /**
+ * <p>
+ * Set the current my location tracking mode.
+ * </p>
+ * <p>
+ * Will enable my location if not active.
+ * </p>
+ * See {@link MyLocationTracking} for different values.
+ *
+ * @param myLocationTrackingMode The location tracking mode to be used.
+ * @throws SecurityException if no suitable permission is present
+ * @see MyLocationTracking
+ */
+ @UiThread
+ public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
+ myLocationView.setMyLocationTrackingMode(myLocationTrackingMode);
- /**
- * Returns if the tracking modes will be dismissed when a gesture occurs.
- *
- * @return True to indicate the tracking modes will be dismissed.
- * @deprecated use @link #isAllDismissTrackingOnGestureinstead
- */
- @Deprecated
- public boolean isDismissTrackingOnGesture() {
- return dismissLocationTrackingOnGesture && dismissBearingTrackingOnGesture;
+ if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
+ focalPointChangedListener.onFocalPointChanged(new PointF(myLocationView.getCenterX(),
+ myLocationView.getCenterY()));
+ } else {
+ focalPointChangedListener.onFocalPointChanged(null);
}
- /**
- * Returns if all tracking modes will be dismissed when a gesture occurs.
- *
- * @return True to indicate that location and bearing tracking will be dismissed.
- */
- public boolean isAllDismissTrackingOnGesture() {
- return dismissLocationTrackingOnGesture && dismissBearingTrackingOnGesture;
+ if (onMyLocationTrackingModeChangeListener != null) {
+ onMyLocationTrackingModeChangeListener.onMyLocationTrackingModeChange(myLocationTrackingMode);
}
+ }
- /**
- * Set the dismissal of the tracking modes if a gesture occurs.
- *
- * @param dismissTrackingOnGesture True to dismiss the tracking modes.
- * @deprecated use @link #setDismissAllTrackingOnGesture instead
- */
- @Deprecated
- public void setDismissTrackingOnGesture(boolean dismissTrackingOnGesture) {
- setDismissAllTrackingOnGesture(dismissTrackingOnGesture);
- }
+ /**
+ * Returns the current user location tracking mode.
+ *
+ * @return The current user location tracking mode.
+ * One of the values from {@link MyLocationTracking.Mode}.
+ * @see MyLocationTracking.Mode
+ */
+ @UiThread
+ @MyLocationTracking.Mode
+ public int getMyLocationTrackingMode() {
+ return myLocationView.getMyLocationTrackingMode();
+ }
- /**
- * Set the dismissal of the tracking modes if a gesture occurs.
- *
- * @param dismissTrackingOnGesture True to dismiss all the tracking modes.
- */
- public void setDismissAllTrackingOnGesture(boolean dismissTrackingOnGesture) {
- dismissLocationTrackingOnGesture = dismissTrackingOnGesture;
- dismissBearingTrackingOnGesture = dismissTrackingOnGesture;
+ /**
+ * <p>
+ * Set the current my bearing tracking mode.
+ * </p>
+ * Shows the direction the user is heading.
+ * <p>
+ * When location tracking is disabled the direction of {@link MyLocationView} is rotated. When
+ * location tracking is enabled the {@link MapView} is rotated based on the bearing value.
+ * </p>
+ * See {@link MyBearingTracking} for different values.
+ *
+ * @param myBearingTrackingMode The bearing tracking mode to be used.
+ * @throws SecurityException if no suitable permission is present
+ * @see MyBearingTracking
+ */
+ @UiThread
+ public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) {
+ myLocationView.setMyBearingTrackingMode(myBearingTrackingMode);
+ if (onMyBearingTrackingModeChangeListener != null) {
+ onMyBearingTrackingModeChangeListener.onMyBearingTrackingModeChange(myBearingTrackingMode);
}
+ }
- /**
- * Set the dismissal of the tracking modes if a gesture occurs.
- *
- * @param dismissLocationTrackingOnGesture True to dismiss the location tracking mode.
- */
- public void setDismissLocationTrackingOnGesture(boolean dismissLocationTrackingOnGesture) {
- this.dismissLocationTrackingOnGesture = dismissLocationTrackingOnGesture;
- }
+ /**
+ * Returns the current user bearing tracking mode.
+ * See {@link MyBearingTracking} for possible return values.
+ *
+ * @return the current user bearing tracking mode.
+ * @see MyBearingTracking
+ */
+ @UiThread
+ @MyBearingTracking.Mode
+ public int getMyBearingTrackingMode() {
+ return myLocationView.getMyBearingTrackingMode();
+ }
- /**
- * Returns if the location tracking will be disabled when a gesture occurs
- *
- * @return True if location tracking will be disabled.
- */
- public boolean isDismissLocationTrackingOnGesture() {
- return dismissLocationTrackingOnGesture;
- }
+ /**
+ * Returns if the tracking modes will be dismissed when a gesture occurs.
+ *
+ * @return True to indicate the tracking modes will be dismissed.
+ * @deprecated use @link #isAllDismissTrackingOnGestureinstead
+ */
+ @Deprecated
+ public boolean isDismissTrackingOnGesture() {
+ return dismissLocationTrackingOnGesture && dismissBearingTrackingOnGesture;
+ }
- /**
- * Set the dismissal of the bearing tracking modes if a gesture occurs.
- *
- * @param dismissBearingTrackingOnGesture True to dimsiss the bearinf tracking mode
- */
- public void setDismissBearingTrackingOnGesture(boolean dismissBearingTrackingOnGesture) {
- this.dismissBearingTrackingOnGesture = dismissBearingTrackingOnGesture;
- }
+ /**
+ * Returns if all tracking modes will be dismissed when a gesture occurs.
+ *
+ * @return True to indicate that location and bearing tracking will be dismissed.
+ */
+ public boolean isAllDismissTrackingOnGesture() {
+ return dismissLocationTrackingOnGesture && dismissBearingTrackingOnGesture;
+ }
+
+ /**
+ * Set the dismissal of the tracking modes if a gesture occurs.
+ *
+ * @param dismissTrackingOnGesture True to dismiss the tracking modes.
+ * @deprecated use @link #setDismissAllTrackingOnGesture instead
+ */
+ @Deprecated
+ public void setDismissTrackingOnGesture(boolean dismissTrackingOnGesture) {
+ setDismissAllTrackingOnGesture(dismissTrackingOnGesture);
+ }
+
+ /**
+ * Set the dismissal of the tracking modes if a gesture occurs.
+ *
+ * @param dismissTrackingOnGesture True to dismiss all the tracking modes.
+ */
+ public void setDismissAllTrackingOnGesture(boolean dismissTrackingOnGesture) {
+ dismissLocationTrackingOnGesture = dismissTrackingOnGesture;
+ dismissBearingTrackingOnGesture = dismissTrackingOnGesture;
+ }
+
+ /**
+ * Set the dismissal of the tracking modes if a gesture occurs.
+ *
+ * @param dismissLocationTrackingOnGesture True to dismiss the location tracking mode.
+ */
+ public void setDismissLocationTrackingOnGesture(boolean dismissLocationTrackingOnGesture) {
+ this.dismissLocationTrackingOnGesture = dismissLocationTrackingOnGesture;
+ }
+
+ /**
+ * Returns if the location tracking will be disabled when a gesture occurs
+ *
+ * @return True if location tracking will be disabled.
+ */
+ public boolean isDismissLocationTrackingOnGesture() {
+ return dismissLocationTrackingOnGesture;
+ }
+
+ /**
+ * Set the dismissal of the bearing tracking modes if a gesture occurs.
+ *
+ * @param dismissBearingTrackingOnGesture True to dimsiss the bearinf tracking mode
+ */
+ public void setDismissBearingTrackingOnGesture(boolean dismissBearingTrackingOnGesture) {
+ this.dismissBearingTrackingOnGesture = dismissBearingTrackingOnGesture;
+ }
+
+ /**
+ * Returns if bearing will disabled when a gesture occurs
+ *
+ * @return True if bearing tracking will be disabled
+ */
+ public boolean isDismissBearingTrackingOnGesture() {
+ return dismissBearingTrackingOnGesture;
+ }
- /**
- * Returns if bearing will disabled when a gesture occurs
- *
- * @return True if bearing tracking will be disabled
- */
- public boolean isDismissBearingTrackingOnGesture() {
- return dismissBearingTrackingOnGesture;
+ /**
+ * Returns if location tracking is disabled
+ *
+ * @return True if location tracking is disabled.
+ */
+ public boolean isLocationTrackingDisabled() {
+ return myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE;
+ }
+
+ /**
+ * Returns if bearing tracking disabled
+ *
+ * @return True if bearing tracking is disabled.
+ */
+ public boolean isBearingTrackingDisabled() {
+ return myLocationView.getMyBearingTrackingMode() == MyBearingTracking.NONE;
+ }
+
+ /**
+ * Returns if rotate gesture are currently enabled.
+ *
+ * @return True if rotate gestures are currently enabled.
+ */
+ public boolean isRotateGestureCurrentlyEnabled() {
+ // rotate gestures are recognised if:
+ // The user settings are enabled AND;
+ // EITHER bearing tracking is dismissed on gesture OR there is no bearing tracking
+ return uiSettings.isRotateGesturesEnabled()
+ && (dismissBearingTrackingOnGesture
+ || myLocationView.getMyBearingTrackingMode() == MyBearingTracking.NONE
+ || myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE);
+ }
+
+ /**
+ * Returns if scroll gesture are currently enabled.
+ *
+ * @return True if scroll gestures are currently enabled.
+ */
+ public boolean isScrollGestureCurrentlyEnabled() {
+ return uiSettings.isScrollGesturesEnabled()
+ && (dismissLocationTrackingOnGesture
+ || myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE);
+ }
+
+ /**
+ * Reset the tracking modes as necessary. Location tracking is reset if the map center is changed,
+ * bearing tracking if there is a rotation.
+ *
+ * @param translate true if translation
+ * @param rotate true if rotation
+ */
+ void resetTrackingModesIfRequired(boolean translate, boolean rotate) {
+ // if tracking is on, and we should dismiss tracking with gestures, and this is a scroll action, turn tracking off
+ if (translate && !isLocationTrackingDisabled() && isDismissLocationTrackingOnGesture()) {
+ setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE);
}
- /**
- * Returns if location tracking is disabled
- *
- * @return True if location tracking is disabled.
- */
- public boolean isLocationTrackingDisabled() {
- return myLocationTrackingMode == MyLocationTracking.TRACKING_NONE;
+ // reset bearing tracking only on rotate
+ if (rotate && !isBearingTrackingDisabled() && isDismissBearingTrackingOnGesture()) {
+ setMyBearingTrackingMode(MyBearingTracking.NONE);
}
+ }
- /**
- * Returns if bearing tracking disabled
- *
- * @return True if bearing tracking is disabled.
- */
- public boolean isBearingTrackingDisabled() {
- return myBearingTrackingMode == MyBearingTracking.NONE;
+ void resetTrackingModesIfRequired(CameraPosition cameraPosition) {
+ resetTrackingModesIfRequired(cameraPosition.target != null, cameraPosition.bearing != -1);
+ }
+
+ Location getMyLocation() {
+ return myLocationView.getLocation();
+ }
+
+ void setOnMyLocationChangeListener(@Nullable final MapboxMap.OnMyLocationChangeListener listener) {
+ if (listener != null) {
+ myLocationListener = new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ if (listener != null) {
+ listener.onMyLocationChange(location);
+ }
+ }
+ };
+ LocationServices.getLocationServices(myLocationView.getContext()).addLocationListener(myLocationListener);
+ } else {
+ LocationServices.getLocationServices(myLocationView.getContext()).removeLocationListener(myLocationListener);
+ myLocationListener = null;
}
+ }
+
+ boolean isPermissionsAccepted() {
+ return (ContextCompat.checkSelfPermission(myLocationView.getContext(),
+ Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED)
+ || ContextCompat.checkSelfPermission(myLocationView.getContext(),
+ Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
+ }
- /**
- * Returns if rotate gesture are currently enabled.
- *
- * @return True if rotate gestures are currently enabled.
- */
- public boolean isRotateGestureCurrentlyEnabled() {
- // rotate gestures are recognised if:
- // The user settings are enabled AND;
- // EITHER bearing tracking is dismissed on gesture OR there is no bearing tracking
- return uiSettings.isRotateGesturesEnabled() &&
- (dismissBearingTrackingOnGesture || myBearingTrackingMode == MyBearingTracking.NONE);
+ void setOnMyLocationTrackingModeChangeListener(MapboxMap.OnMyLocationTrackingModeChangeListener listener) {
+ this.onMyLocationTrackingModeChangeListener = listener;
+ }
+
+ void setOnMyBearingTrackingModeChangeListener(MapboxMap.OnMyBearingTrackingModeChangeListener listener) {
+ this.onMyBearingTrackingModeChangeListener = listener;
+ }
+
+ MyLocationView getMyLocationView() {
+ return myLocationView;
+ }
+
+
+ boolean isMyLocationEnabled() {
+ return myLocationEnabled;
+ }
+
+ void setMyLocationEnabled(boolean locationEnabled) {
+ if (!isPermissionsAccepted()) {
+ Timber.e("Could not activate user location tracking: "
+ + "user did not accept the permission or permissions were not requested.");
+ return;
}
+ myLocationEnabled = locationEnabled;
+ myLocationView.setEnabled(locationEnabled);
+ }
- /**
- * Returns if scroll gesture are currently enabled.
- *
- * @return True if scroll gestures are currently enabled.
- */
- public boolean isScrollGestureCurrentlyEnabled() {
- return uiSettings.isScrollGesturesEnabled() &&
- (dismissLocationTrackingOnGesture || myLocationTrackingMode == MyLocationTracking.TRACKING_NONE);
+ void update() {
+ if (!myLocationView.isEnabled()) {
+ return;
}
+ myLocationView.update();
+ }
+
+ void onStart() {
+ myLocationView.onStart();
+ }
+
+ void onStop() {
+ myLocationView.onStop();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java
new file mode 100644
index 0000000000..88acc13356
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java
@@ -0,0 +1,300 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.UiThread;
+
+import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdate;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
+
+import java.util.concurrent.TimeUnit;
+
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.maps.MapView.REGION_DID_CHANGE_ANIMATED;
+
+/**
+ * Resembles the current Map transformation.
+ * <p>
+ * Responsible for synchronising {@link CameraPosition} state and notifying
+ * {@link com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraChangeListener}.
+ * </p>
+ */
+final class Transform implements MapView.OnMapChangedListener {
+
+ private final NativeMapView mapView;
+ private final MarkerViewManager markerViewManager;
+ private final TrackingSettings trackingSettings;
+ private final MyLocationView myLocationView;
+
+ private CameraPosition cameraPosition;
+ private MapboxMap.CancelableCallback cameraCancelableCallback;
+ private MapboxMap.OnCameraChangeListener onCameraChangeListener;
+
+ Transform(NativeMapView mapView, MarkerViewManager markerViewManager, TrackingSettings trackingSettings) {
+ this.mapView = mapView;
+ this.markerViewManager = markerViewManager;
+ this.trackingSettings = trackingSettings;
+ this.myLocationView = trackingSettings.getMyLocationView();
+ }
+
+ void initialise(@NonNull MapboxMap mapboxMap, @NonNull MapboxMapOptions options) {
+ CameraPosition position = options.getCamera();
+ if (position != null && !position.equals(CameraPosition.DEFAULT)) {
+ moveCamera(mapboxMap, CameraUpdateFactory.newCameraPosition(position), null);
+ }
+ }
+
+ //
+ // Camera API
+ //
+
+ @UiThread
+ public final CameraPosition getCameraPosition() {
+ if (cameraPosition == null) {
+ cameraPosition = invalidateCameraPosition();
+ }
+ return cameraPosition;
+ }
+
+ @UiThread
+ void updateCameraPosition(@NonNull CameraPosition position) {
+ if (myLocationView != null) {
+ myLocationView.setCameraPosition(position);
+ }
+ markerViewManager.setTilt((float) position.tilt);
+ }
+
+ @Override
+ public void onMapChanged(@MapView.MapChange int change) {
+ if (change == REGION_DID_CHANGE_ANIMATED && cameraCancelableCallback != null) {
+ invalidateCameraPosition();
+ if (cameraCancelableCallback != null) {
+ cameraCancelableCallback.onFinish();
+ cameraCancelableCallback = null;
+ }
+ mapView.removeOnMapChangedListener(this);
+ }
+ }
+
+ @UiThread
+ final void moveCamera(MapboxMap mapboxMap, CameraUpdate update, MapboxMap.CancelableCallback callback) {
+ cameraPosition = update.getCameraPosition(mapboxMap);
+ trackingSettings.resetTrackingModesIfRequired(cameraPosition);
+ cancelTransitions();
+ mapView.jumpTo(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom);
+ if (callback != null) {
+ callback.onFinish();
+ }
+ }
+
+ @UiThread
+ final void easeCamera(MapboxMap mapboxMap, CameraUpdate update, int durationMs, boolean easingInterpolator,
+ boolean resetTrackingMode, final MapboxMap.CancelableCallback callback) {
+ cameraPosition = update.getCameraPosition(mapboxMap);
+ if (resetTrackingMode) {
+ trackingSettings.resetTrackingModesIfRequired(cameraPosition);
+ }
+
+ cancelTransitions();
+ if (callback != null) {
+ cameraCancelableCallback = callback;
+ mapView.addOnMapChangedListener(this);
+ }
+
+ mapView.easeTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt,
+ cameraPosition.zoom, easingInterpolator);
+ }
+
+ @UiThread
+ final void animateCamera(MapboxMap mapboxMap, CameraUpdate update, int durationMs,
+ final MapboxMap.CancelableCallback callback) {
+ cameraPosition = update.getCameraPosition(mapboxMap);
+ trackingSettings.resetTrackingModesIfRequired(cameraPosition);
+
+ cancelTransitions();
+ if (callback != null) {
+ cameraCancelableCallback = callback;
+ mapView.addOnMapChangedListener(this);
+ }
+
+ mapView.flyTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt,
+ cameraPosition.zoom);
+ }
+
+ @UiThread
+ @Nullable
+ CameraPosition invalidateCameraPosition() {
+ if (mapView != null) {
+ cameraPosition = new CameraPosition.Builder(mapView.getCameraValues()).build();
+ if (onCameraChangeListener != null) {
+ onCameraChangeListener.onCameraChange(this.cameraPosition);
+ }
+ }
+ return cameraPosition;
+ }
+
+ void cancelTransitions() {
+ if (cameraCancelableCallback != null) {
+ cameraCancelableCallback.onCancel();
+ cameraCancelableCallback = null;
+ }
+ mapView.cancelTransitions();
+ }
+
+ @UiThread
+ void resetNorth() {
+ cancelTransitions();
+ mapView.resetNorth();
+ }
+
+ void setOnCameraChangeListener(@Nullable MapboxMap.OnCameraChangeListener listener) {
+ this.onCameraChangeListener = listener;
+ }
+
+ private long getDurationNano(long durationMs) {
+ return durationMs > 0 ? TimeUnit.NANOSECONDS.convert(durationMs, TimeUnit.MILLISECONDS) : 0;
+ }
+
+ //
+ // non Camera API
+ //
+
+ // Zoom in or out
+
+ double getZoom() {
+ return cameraPosition.zoom;
+ }
+
+ void zoom(boolean zoomIn) {
+ zoom(zoomIn, -1.0f, -1.0f);
+ }
+
+ void zoom(boolean zoomIn, float x, float y) {
+ // Cancel any animation
+ cancelTransitions();
+
+ if (zoomIn) {
+ mapView.scaleBy(2.0, x, y, MapboxConstants.ANIMATION_DURATION);
+ } else {
+ mapView.scaleBy(0.5, x, y, MapboxConstants.ANIMATION_DURATION);
+ }
+ }
+
+ // Direction
+ double getBearing() {
+ double direction = -mapView.getBearing();
+
+ while (direction > 360) {
+ direction -= 360;
+ }
+ while (direction < 0) {
+ direction += 360;
+ }
+
+ return direction;
+ }
+
+ double getRawBearing() {
+ return mapView.getBearing();
+ }
+
+ void setBearing(double bearing) {
+ if (myLocationView != null) {
+ myLocationView.setBearing(bearing);
+ }
+ mapView.setBearing(bearing);
+ }
+
+ void setBearing(double bearing, float focalX, float focalY) {
+ if (myLocationView != null) {
+ myLocationView.setBearing(bearing);
+ }
+ mapView.setBearing(bearing, focalX, focalY);
+ }
+
+
+ //
+ // LatLng / CenterCoordinate
+ //
+
+ LatLng getLatLng() {
+ return mapView.getLatLng();
+ }
+
+ //
+ // Pitch / Tilt
+ //
+
+ double getTilt() {
+ return mapView.getPitch();
+ }
+
+ void setTilt(Double pitch) {
+ if (myLocationView != null) {
+ myLocationView.setTilt(pitch);
+ }
+ markerViewManager.setTilt(pitch.floatValue());
+ mapView.setPitch(pitch, 0);
+ }
+
+ //
+ // Center coordinate
+ //
+
+ LatLng getCenterCoordinate() {
+ return mapView.getLatLng();
+ }
+
+ void setCenterCoordinate(LatLng centerCoordinate) {
+ mapView.setLatLng(centerCoordinate);
+ }
+
+ void setGestureInProgress(boolean gestureInProgress) {
+ mapView.setGestureInProgress(gestureInProgress);
+ if (!gestureInProgress) {
+ invalidateCameraPosition();
+ }
+ }
+
+ void zoomBy(double pow, float x, float y) {
+ mapView.scaleBy(pow, x, y);
+ }
+
+ void moveBy(double offsetX, double offsetY, long duration) {
+ mapView.moveBy(offsetX, offsetY, duration);
+ }
+
+ //
+ // Min & Max ZoomLevel
+ //
+
+ void setMinZoom(double minZoom) {
+ if ((minZoom < MapboxConstants.MINIMUM_ZOOM) || (minZoom > MapboxConstants.MAXIMUM_ZOOM)) {
+ Timber.e("Not setting minZoomPreference, value is in unsupported range: " + minZoom);
+ return;
+ }
+ mapView.setMinZoom(minZoom);
+ }
+
+ double getMinZoom() {
+ return mapView.getMinZoom();
+ }
+
+ void setMaxZoom(double maxZoom) {
+ if ((maxZoom < MapboxConstants.MINIMUM_ZOOM) || (maxZoom > MapboxConstants.MAXIMUM_ZOOM)) {
+ Timber.e("Not setting maxZoomPreference, value is in unsupported range: " + maxZoom);
+ return;
+ }
+ mapView.setMaxZoom(maxZoom);
+ }
+
+ double getMaxZoom() {
+ return mapView.getMaxZoom();
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
index d6ad80d11e..bb5271313b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
@@ -1,635 +1,843 @@
package com.mapbox.mapboxsdk.maps;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.Color;
import android.graphics.PointF;
+import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
+import android.support.v4.content.ContextCompat;
import android.view.Gravity;
import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.mapbox.mapboxsdk.R;
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.maps.widgets.CompassView;
+import com.mapbox.mapboxsdk.utils.ColorUtils;
/**
* Settings for the user interface of a MapboxMap. To obtain this interface, call getUiSettings().
*/
-public class UiSettings {
-
- private MapView mapView;
-
- private CompassViewSettings compassSettings;
- private ViewSettings logoSettings;
- private ViewSettings attributionSettings;
-
- private boolean rotateGesturesEnabled = true;
- private boolean rotateGestureChangeAllowed = true;
-
- private boolean tiltGesturesEnabled = true;
- private boolean tiltGestureChangeAllowed = true;
-
- private boolean zoomGesturesEnabled = true;
- private boolean zoomGestureChangeAllowed = true;
-
- private boolean scrollGesturesEnabled = true;
- private boolean scrollGestureChangeAllowed = true;
-
- private boolean zoomControlsEnabled;
-
- private boolean deselectMarkersOnTap = true;
-
- private PointF focalPoint;
-
- UiSettings(@NonNull MapView mapView) {
- this.mapView = mapView;
- this.compassSettings = new CompassViewSettings();
- this.logoSettings = new ViewSettings();
- this.attributionSettings = new ViewSettings();
- }
-
- /**
- * <p>
- * Enables or disables the compass. The compass is an icon on the map that indicates the
- * direction of north on the map. When a user clicks
- * the compass, the camera orients itself to its default orientation and fades away shortly
- * after. If disabled, the compass will never be displayed.
- * </p>
- * By default, the compass is enabled.
- *
- * @param compassEnabled True to enable the compass; false to disable the compass.
- */
- public void setCompassEnabled(boolean compassEnabled) {
- compassSettings.setEnabled(compassEnabled);
- mapView.setCompassEnabled(compassEnabled);
- }
-
- /**
- * Returns whether the compass is enabled.
- *
- * @return True if the compass is enabled; false if the compass is disabled.
- */
- public boolean isCompassEnabled() {
- return compassSettings.isEnabled();
- }
-
- /**
- * <p>
- * Sets the gravity of the compass view. Use this to change the corner of the map view that the
- * compass is displayed in.
- * </p>
- * By default, the compass is in the top right corner.
- *
- * @param gravity One of the values from {@link Gravity}.
- * @see Gravity
- */
- @UiThread
- public void setCompassGravity(int gravity) {
- compassSettings.setGravity(gravity);
- mapView.setCompassGravity(gravity);
- }
-
- /**
- * Enables or disables fading of the compass when facing north.
- * <p>
- * By default this feature is enabled
- * </p>
- *
- * @param compassFadeFacingNorth True to enable the fading animation; false to disable it
- */
- public void setCompassFadeFacingNorth(boolean compassFadeFacingNorth) {
- compassSettings.setFadeFacingNorth(compassFadeFacingNorth);
- mapView.setCompassFadeFacingNorth(compassFadeFacingNorth);
- }
-
- /**
- * Returns whether the compass performs a fading animation out when facing north.
- *
- * @return True if the compass will fade, false if it remains visible
- */
- public boolean isCompassFadeWhenFacingNorth(){
- return compassSettings.isFadeFacingNorth();
- }
-
- /**
- * Returns the gravity value of the CompassView
- *
- * @return The gravity
- */
- public int getCompassGravity() {
- return compassSettings.getGravity();
- }
-
- /**
- * Sets the margins of the compass view. Use this to change the distance of the compass from the
- * map view edge.
- *
- * @param left The left margin in pixels.
- * @param top The top margin in pixels.
- * @param right The right margin in pixels.
- * @param bottom The bottom margin in pixels.
- */
- @UiThread
- public void setCompassMargins(int left, int top, int right, int bottom) {
- compassSettings.setMargins(new int[]{left, top, right, bottom});
- mapView.setCompassMargins(left, top, right, bottom);
- }
-
- /**
- * Returns the left side margin of CompassView
- *
- * @return The left margin in pixels
- */
- public int getCompassMarginLeft() {
- return compassSettings.getMargins()[0];
- }
-
- /**
- * Returns the top side margin of CompassView
- *
- * @return The top margin in pixels
- */
- public int getCompassMarginTop() {
- return compassSettings.getMargins()[1];
- }
-
- /**
- * Returns the right side margin of CompassView
- *
- * @return The right margin in pixels
- */
- public int getCompassMarginRight() {
- return compassSettings.getMargins()[2];
- }
-
- /**
- * Returns the bottom side margin of CompassView
- *
- * @return The bottom margin in pixels
- */
- public int getCompassMarginBottom() {
- return compassSettings.getMargins()[3];
- }
-
- /**
- * <p>
- * Enables or disables the Mapbox logo.
- * </p>
- * By default, the compass is enabled.
- *
- * @param enabled True to enable the logo; false to disable the logo.
- */
- public void setLogoEnabled(boolean enabled) {
- logoSettings.setEnabled(enabled);
- mapView.setLogoEnabled(enabled);
- }
-
- /**
- * Returns whether the logo is enabled.
- *
- * @return True if the logo is enabled; false if the logo is disabled.
- */
- public boolean isLogoEnabled() {
- return logoSettings.isEnabled();
- }
-
- /**
- * <p>
- * Sets the gravity of the logo view. Use this to change the corner of the map view that the
- * Mapbox logo is displayed in.
- * </p>
- * By default, the logo is in the bottom left corner.
- *
- * @param gravity One of the values from {@link Gravity}.
- * @see Gravity
- */
- public void setLogoGravity(int gravity) {
- logoSettings.setGravity(gravity);
- mapView.setLogoGravity(gravity);
- }
-
- /**
- * Returns the gravity value of the logo
- *
- * @return The gravity
- */
- public int getLogoGravity() {
- return logoSettings.getGravity();
- }
-
- /**
- * Sets the margins of the logo view. Use this to change the distance of the Mapbox logo from the
- * map view edge.
- *
- * @param left The left margin in pixels.
- * @param top The top margin in pixels.
- * @param right The right margin in pixels.
- * @param bottom The bottom margin in pixels.
- */
- public void setLogoMargins(int left, int top, int right, int bottom) {
- logoSettings.setMargins(new int[]{left, top, right, bottom});
- mapView.setLogoMargins(left, top, right, bottom);
- }
-
- /**
- * Returns the left side margin of the logo
- *
- * @return The left margin in pixels
- */
- public int getLogoMarginLeft() {
- return logoSettings.getMargins()[0];
- }
-
- /**
- * Returns the top side margin of the logo
- *
- * @return The top margin in pixels
- */
- public int getLogoMarginTop() {
- return logoSettings.getMargins()[1];
- }
-
- /**
- * Returns the right side margin of the logo
- *
- * @return The right margin in pixels
- */
- public int getLogoMarginRight() {
- return logoSettings.getMargins()[2];
- }
-
- /**
- * Returns the bottom side margin of the logo
- *
- * @return The bottom margin in pixels
- */
- public int getLogoMarginBottom() {
- return logoSettings.getMargins()[3];
- }
-
- /**
- * <p>
- * Enables or disables the attribution.
- * </p>
- * By default, the attribution is enabled.
- *
- * @param enabled True to enable the attribution; false to disable the attribution.
- */
- public void setAttributionEnabled(boolean enabled) {
- attributionSettings.setEnabled(enabled);
- mapView.setAttributionEnabled(enabled ? View.VISIBLE : View.GONE);
- }
-
- /**
- * Returns whether the attribution is enabled.
- *
- * @return True if the attribution is enabled; false if the attribution is disabled.
- */
- public boolean isAttributionEnabled() {
- return attributionSettings.isEnabled();
- }
-
- /**
- * <p>
- * Sets the gravity of the attribution.
- * </p>
- * By default, the attribution is in the bottom left corner next to the Mapbox logo.
- *
- * @param gravity One of the values from {@link Gravity}.
- * @see Gravity
- */
- public void setAttributionGravity(int gravity) {
- attributionSettings.setGravity(gravity);
- mapView.setAttributionGravity(gravity);
- }
-
- /**
- * Returns the gravity value of the logo
- *
- * @return The gravity
- */
- public int getAttributionGravity() {
- return attributionSettings.getGravity();
- }
-
- /**
- * Sets the margins of the attribution view.
- *
- * @param left The left margin in pixels.
- * @param top The top margin in pixels.
- * @param right The right margin in pixels.
- * @param bottom The bottom margin in pixels.
- */
- public void setAttributionMargins(int left, int top, int right, int bottom) {
- attributionSettings.setMargins(new int[]{left, top, right, bottom});
- mapView.setAttributionMargins(left, top, right, bottom);
- }
-
- /**
- * <p>
- * Sets the tint of the attribution view. Use this to change the color of the attribution.
- * </p>
- * By default, the logo is tinted with the primary color of your theme.
- *
- * @param tintColor Color to tint the attribution.
- */
- public void setAttributionTintColor(@ColorInt int tintColor) {
- attributionSettings.setTintColor(tintColor);
- mapView.setAtttibutionTintColor(tintColor);
- }
-
- /**
- * Returns the tint color value of the attribution view.
- *
- * @return The tint color
- */
- public int getAttributionTintColor() {
- return attributionSettings.getTintColor();
- }
-
- /**
- * Returns the left side margin of the attribution view.
- *
- * @return The left margin in pixels
- */
- public int getAttributionMarginLeft() {
- return attributionSettings.getMargins()[0];
- }
-
- /**
- * Returns the top side margin of the attribution view.
- *
- * @return The top margin in pixels
- */
- public int getAttributionMarginTop() {
- return attributionSettings.getMargins()[1];
- }
-
- /**
- * Returns the right side margin of the attribution view.
- *
- * @return The right margin in pixels
- */
- public int getAttributionMarginRight() {
- return attributionSettings.getMargins()[2];
- }
-
- /**
- * Returns the bottom side margin of the logo
- *
- * @return The bottom margin in pixels
- */
- public int getAttributionMarginBottom() {
- return attributionSettings.getMargins()[3];
- }
-
- /**
- * <p>
- * Changes whether the user may rotate the map.
- * </p>
- * <p>
- * This setting controls only user interactions with the map. If you set the value to false,
- * you may still change the map location programmatically.
- * </p>
- * The default value is true.
- *
- * @param rotateGesturesEnabled If true, rotating is enabled.
- */
- public void setRotateGesturesEnabled(boolean rotateGesturesEnabled) {
- if (rotateGestureChangeAllowed) {
- this.rotateGesturesEnabled = rotateGesturesEnabled;
- }
- }
-
- /**
- * Returns whether the user may rotate the map.
- *
- * @return If true, rotating is enabled.
- */
- public boolean isRotateGesturesEnabled() {
- return rotateGesturesEnabled;
- }
-
- void setRotateGestureChangeAllowed(boolean rotateGestureChangeAllowed) {
- this.rotateGestureChangeAllowed = rotateGestureChangeAllowed;
- }
-
- boolean isRotateGestureChangeAllowed() {
- return rotateGestureChangeAllowed;
- }
-
- /**
- * <p>
- * Changes whether the user may tilt the map.
- * </p>
- * <p>
- * This setting controls only user interactions with the map. If you set the value to false,
- * you may still change the map location programmatically.
- * </p>
- * The default value is true.
- *
- * @param tiltGesturesEnabled If true, tilting is enabled.
- */
- public void setTiltGesturesEnabled(boolean tiltGesturesEnabled) {
- if (tiltGestureChangeAllowed) {
- this.tiltGesturesEnabled = tiltGesturesEnabled;
- }
- }
-
- /**
- * Returns whether the user may tilt the map.
- *
- * @return If true, tilting is enabled.
- */
- public boolean isTiltGesturesEnabled() {
- return tiltGesturesEnabled;
- }
-
- void setTiltGestureChangeAllowed(boolean tiltGestureChangeAllowed) {
- this.tiltGestureChangeAllowed = tiltGestureChangeAllowed;
- }
-
- boolean isTiltGestureChangeAllowed() {
- return tiltGestureChangeAllowed;
- }
-
- /**
- * <p>
- * Changes whether the user may zoom the map.
- * </p>
- * <p>
- * This setting controls only user interactions with the map. If you set the value to false,
- * you may still change the map location programmatically.
- * </p>
- * The default value is true.
- *
- * @param zoomGesturesEnabled If true, zooming is enabled.
- */
- public void setZoomGesturesEnabled(boolean zoomGesturesEnabled) {
- if (zoomGestureChangeAllowed) {
- this.zoomGesturesEnabled = zoomGesturesEnabled;
- }
- }
-
- /**
- * Returns whether the user may zoom the map.
- *
- * @return If true, zooming is enabled.
- */
- public boolean isZoomGesturesEnabled() {
- return zoomGesturesEnabled;
- }
-
- void setZoomGestureChangeAllowed(boolean zoomGestureChangeAllowed) {
- this.zoomGestureChangeAllowed = zoomGestureChangeAllowed;
- }
-
- boolean isZoomGestureChangeAllowed() {
- return zoomGestureChangeAllowed;
- }
-
- /**
- * <p>
- * Sets whether the zoom controls are enabled.
- * If enabled, the zoom controls are a pair of buttons
- * (one for zooming in, one for zooming out) that appear on the screen.
- * When pressed, they cause the camera to zoom in (or out) by one zoom level.
- * If disabled, the zoom controls are not shown.
- * </p>
- * By default the zoom controls are enabled if the device is only single touch capable;
- *
- * @param zoomControlsEnabled If true, the zoom controls are enabled.
- */
- public void setZoomControlsEnabled(boolean zoomControlsEnabled) {
- this.zoomControlsEnabled = zoomControlsEnabled;
- }
-
- /**
- * Gets whether the zoom controls are enabled.
- *
- * @return If true, the zoom controls are enabled.
- */
- public boolean isZoomControlsEnabled() {
- return zoomControlsEnabled;
- }
-
- /**
- * Gets whether the markers are automatically deselected (and therefore, their infowindows
- * closed) when a map tap is detected.
- *
- * @return If true, markers are deselected on a map tap.
- */
- public boolean isDeselectMarkersOnTap() {
- return deselectMarkersOnTap;
- }
-
- /**
- * Sets whether the markers are automatically deselected (and therefore, their infowindows
- * closed) when a map tap is detected.
- *
- * @param deselectMarkersOnTap determines if markers should be deslected on tap
- */
- public void setDeselectMarkersOnTap(boolean deselectMarkersOnTap) {
- this.deselectMarkersOnTap = deselectMarkersOnTap;
- }
-
- /**
- * <p>
- * Changes whether the user may scroll around the map.
- * </p>
- * <p>
- * This setting controls only user interactions with the map. If you set the value to false,
- * you may still change the map location programmatically.
- * </p>
- * The default value is true.
- *
- * @param scrollGesturesEnabled If true, scrolling is enabled.
- */
- public void setScrollGesturesEnabled(boolean scrollGesturesEnabled) {
- if (scrollGestureChangeAllowed) {
- this.scrollGesturesEnabled = scrollGesturesEnabled;
- }
- }
-
- /**
- * Returns whether the user may scroll around the map.
- *
- * @return If true, scrolling is enabled.
- */
- public boolean isScrollGesturesEnabled() {
- return scrollGesturesEnabled;
- }
-
- void setScrollGestureChangeAllowed(boolean scrollGestureChangeAllowed) {
- this.scrollGestureChangeAllowed = scrollGestureChangeAllowed;
- }
-
- boolean isScrollGestureChangeAllowed() {
- return scrollGestureChangeAllowed;
- }
-
- /**
- * <p>
- * Sets the preference for whether all gestures should be enabled or disabled.
- * </p>
- * <p>
- * This setting controls only user interactions with the map. If you set the value to false,
- * you may still change the map location programmatically.
- * </p>
- * The default value is true.
- *
- * @param enabled If true, all gestures are available; otherwise, all gestures are disabled.
- * @see #setZoomGesturesEnabled(boolean) )
- * @see #setScrollGesturesEnabled(boolean)
- * @see #setRotateGesturesEnabled(boolean)
- * @see #setTiltGesturesEnabled(boolean)
- */
- public void setAllGesturesEnabled(boolean enabled) {
- setScrollGesturesEnabled(enabled);
- setRotateGesturesEnabled(enabled);
- setTiltGesturesEnabled(enabled);
- setZoomGesturesEnabled(enabled);
- }
-
- /**
- * Sets the focal point used as center for a gesture
- *
- * @param focalPoint the focal point to be used.
- */
- public void setFocalPoint(@Nullable PointF focalPoint) {
- this.focalPoint = focalPoint;
- mapView.setFocalPoint(focalPoint);
- }
-
- /**
- * Returns the gesture focal point
- *
- * @return The focal point
- */
- public PointF getFocalPoint() {
- return focalPoint;
- }
-
- /**
- * Returns the measured height of the MapView
- *
- * @return height in pixels
- */
- public float getHeight() {
- return mapView.getMeasuredHeight();
- }
-
- /**
- * Returns the measured width of the MapView
- *
- * @return widht in pixels
- */
- public float getWidth() {
- return mapView.getMeasuredWidth();
- }
-
- /**
- * Invalidates the ViewSettings instances shown on top of the MapView
- */
- public void invalidate() {
- mapView.setLogoMargins(getLogoMarginLeft(), getLogoMarginTop(), getLogoMarginRight(), getLogoMarginBottom());
- mapView.setCompassMargins(getCompassMarginLeft(), getCompassMarginTop(), getCompassMarginRight(), getCompassMarginBottom());
- mapView.setAttributionMargins(getAttributionMarginLeft(), getAttributionMarginTop(), getAttributionMarginRight(), getAttributionMarginBottom());
- }
+public final class UiSettings {
+
+ private final FocalPointChangeListener focalPointChangeListener;
+ private final Projection projection;
+ private final CompassView compassView;
+ private final ImageView attributionsView;
+ private final View logoView;
+ private float pixelRatio;
+
+ private boolean rotateGesturesEnabled = true;
+ private boolean rotateGestureChangeAllowed = true;
+
+ private boolean tiltGesturesEnabled = true;
+ private boolean tiltGestureChangeAllowed = true;
+
+ private boolean zoomGesturesEnabled = true;
+ private boolean zoomGestureChangeAllowed = true;
+
+ private boolean scrollGesturesEnabled = true;
+ private boolean scrollGestureChangeAllowed = true;
+
+ private boolean zoomControlsEnabled;
+
+ private boolean deselectMarkersOnTap = true;
+
+ private PointF userProvidedFocalPoint;
+
+ UiSettings(@NonNull Projection projection, @NonNull FocalPointChangeListener listener,
+ @NonNull CompassView compassView, @NonNull ImageView attributionsView, @NonNull View logoView) {
+ this.projection = projection;
+ this.focalPointChangeListener = listener;
+ this.compassView = compassView;
+ this.attributionsView = attributionsView;
+ this.logoView = logoView;
+ if (logoView.getResources() != null) {
+ this.pixelRatio = logoView.getResources().getDisplayMetrics().density;
+ }
+ }
+
+ void initialise(@NonNull Context context, @NonNull MapboxMapOptions options) {
+ Resources resources = context.getResources();
+ initialiseGestures(options);
+ initialiseCompass(options, resources);
+ initialiseLogo(options, resources);
+ initialiseAttribution(context, options);
+ initialiseZoomControl(context);
+ }
+
+ void onSaveInstanceState(Bundle outState) {
+ saveGestures(outState);
+ saveCompass(outState);
+ saveLogo(outState);
+ saveAttribution(outState);
+ saveZoomControl(outState);
+ }
+
+ void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
+ restoreGestures(savedInstanceState);
+ restoreCompass(savedInstanceState);
+ restoreLogo(savedInstanceState);
+ restoreAttribution(savedInstanceState);
+ restoreZoomControl(savedInstanceState);
+ }
+
+ private void initialiseGestures(MapboxMapOptions options) {
+ setZoomGesturesEnabled(options.getZoomGesturesEnabled());
+ setZoomGestureChangeAllowed(options.getZoomGesturesEnabled());
+ setScrollGesturesEnabled(options.getScrollGesturesEnabled());
+ setScrollGestureChangeAllowed(options.getScrollGesturesEnabled());
+ setRotateGesturesEnabled(options.getRotateGesturesEnabled());
+ setRotateGestureChangeAllowed(options.getRotateGesturesEnabled());
+ setTiltGesturesEnabled(options.getTiltGesturesEnabled());
+ setTiltGestureChangeAllowed(options.getTiltGesturesEnabled());
+ setZoomControlsEnabled(options.getZoomControlsEnabled());
+ }
+
+ private void saveGestures(Bundle outState) {
+ outState.putBoolean(MapboxConstants.STATE_ZOOM_ENABLED, isZoomGesturesEnabled());
+ outState.putBoolean(MapboxConstants.STATE_ZOOM_ENABLED_CHANGE, isZoomGestureChangeAllowed());
+ outState.putBoolean(MapboxConstants.STATE_SCROLL_ENABLED, isScrollGesturesEnabled());
+ outState.putBoolean(MapboxConstants.STATE_SCROLL_ENABLED_CHANGE, isScrollGestureChangeAllowed());
+ outState.putBoolean(MapboxConstants.STATE_ROTATE_ENABLED, isRotateGesturesEnabled());
+ outState.putBoolean(MapboxConstants.STATE_ROTATE_ENABLED_CHANGE, isRotateGestureChangeAllowed());
+ outState.putBoolean(MapboxConstants.STATE_TILT_ENABLED, isTiltGesturesEnabled());
+ outState.putBoolean(MapboxConstants.STATE_TILT_ENABLED_CHANGE, isTiltGestureChangeAllowed());
+ }
+
+ private void restoreGestures(Bundle savedInstanceState) {
+ setZoomGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_ENABLED));
+ setZoomGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_ENABLED_CHANGE));
+ setScrollGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_SCROLL_ENABLED));
+ setScrollGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_SCROLL_ENABLED_CHANGE));
+ setRotateGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ROTATE_ENABLED));
+ setRotateGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_ROTATE_ENABLED_CHANGE));
+ setTiltGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_TILT_ENABLED));
+ setTiltGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_TILT_ENABLED_CHANGE));
+ }
+
+ private void initialiseCompass(MapboxMapOptions options, Resources resources) {
+ setCompassEnabled(options.getCompassEnabled());
+ setCompassGravity(options.getCompassGravity());
+ int[] compassMargins = options.getCompassMargins();
+ if (compassMargins != null) {
+ setCompassMargins(compassMargins[0], compassMargins[1], compassMargins[2], compassMargins[3]);
+ } else {
+ int tenDp = (int) resources.getDimension(R.dimen.mapbox_ten_dp);
+ setCompassMargins(tenDp, tenDp, tenDp, tenDp);
+ }
+ setCompassFadeFacingNorth(options.getCompassFadeFacingNorth());
+ }
+
+ private void saveCompass(Bundle outState) {
+ outState.putBoolean(MapboxConstants.STATE_COMPASS_ENABLED, isCompassEnabled());
+ outState.putInt(MapboxConstants.STATE_COMPASS_GRAVITY, getCompassGravity());
+ outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_LEFT, getCompassMarginLeft());
+ outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_TOP, getCompassMarginTop());
+ outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM, getCompassMarginBottom());
+ outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_RIGHT, getCompassMarginRight());
+ outState.putBoolean(MapboxConstants.STATE_COMPASS_FADE_WHEN_FACING_NORTH, isCompassFadeWhenFacingNorth());
+ }
+
+ private void restoreCompass(Bundle savedInstanceState) {
+ setCompassEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_COMPASS_ENABLED));
+ setCompassGravity(savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_GRAVITY));
+ setCompassMargins(savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_LEFT),
+ savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_TOP),
+ savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_RIGHT),
+ savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM));
+ setCompassFadeFacingNorth(savedInstanceState.getBoolean(MapboxConstants.STATE_COMPASS_FADE_WHEN_FACING_NORTH));
+ }
+
+ private void initialiseLogo(MapboxMapOptions options, Resources resources) {
+ setLogoEnabled(options.getLogoEnabled());
+ setLogoGravity(options.getLogoGravity());
+ int[] logoMargins = options.getLogoMargins();
+ if (logoMargins != null) {
+ setLogoMargins(logoMargins[0], logoMargins[1], logoMargins[2], logoMargins[3]);
+ } else {
+ int sixteenDp = (int) resources.getDimension(R.dimen.mapbox_sixteen_dp);
+ setLogoMargins(sixteenDp, sixteenDp, sixteenDp, sixteenDp);
+ }
+ }
+
+ private void saveLogo(Bundle outState) {
+ outState.putInt(MapboxConstants.STATE_LOGO_GRAVITY, getLogoGravity());
+ outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_LEFT, getLogoMarginLeft());
+ outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_TOP, getLogoMarginTop());
+ outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_RIGHT, getLogoMarginRight());
+ outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_BOTTOM, getLogoMarginBottom());
+ outState.putBoolean(MapboxConstants.STATE_LOGO_ENABLED, isLogoEnabled());
+ }
+
+ private void restoreLogo(Bundle savedInstanceState) {
+ setLogoEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_LOGO_ENABLED));
+ setLogoGravity(savedInstanceState.getInt(MapboxConstants.STATE_LOGO_GRAVITY));
+ setLogoMargins(savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_LEFT),
+ savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_TOP),
+ savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_RIGHT),
+ savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_BOTTOM));
+ }
+
+ private void initialiseAttribution(Context context, MapboxMapOptions options) {
+ Resources resources = context.getResources();
+ setAttributionEnabled(options.getAttributionEnabled());
+ setAttributionGravity(options.getAttributionGravity());
+ int[] attributionMargins = options.getAttributionMargins();
+ if (attributionMargins != null) {
+ setAttributionMargins(attributionMargins[0], attributionMargins[1], attributionMargins[2], attributionMargins[3]);
+ } else {
+ int sevenDp = (int) resources.getDimension(R.dimen.mapbox_seven_dp);
+ int seventySixDp = (int) resources.getDimension(R.dimen.mapbox_seventy_six_dp);
+ setAttributionMargins(seventySixDp, sevenDp, sevenDp, sevenDp);
+ }
+
+ int attributionTintColor = options.getAttributionTintColor();
+ setAttributionTintColor(attributionTintColor != -1
+ ? attributionTintColor : ColorUtils.getPrimaryColor(context));
+ }
+
+ private void saveAttribution(Bundle outState) {
+ outState.putInt(MapboxConstants.STATE_ATTRIBUTION_GRAVITY, getAttributionGravity());
+ outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_LEFT, getAttributionMarginLeft());
+ outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_TOP, getAttributionMarginTop());
+ outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_RIGHT, getAttributionMarginRight());
+ outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_BOTTOM, getAttributionMarginBottom());
+ outState.putBoolean(MapboxConstants.STATE_ATTRIBUTION_ENABLED, isAttributionEnabled());
+ }
+
+ private void restoreAttribution(Bundle savedInstanceState) {
+ setAttributionEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ATTRIBUTION_ENABLED));
+ setAttributionGravity(savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_GRAVITY));
+ setAttributionMargins(savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_LEFT),
+ savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_TOP),
+ savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_RIGHT),
+ savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_BOTTOM));
+ }
+
+ private void initialiseZoomControl(Context context) {
+ if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) {
+ setZoomControlsEnabled(true);
+ }
+ }
+
+ private void saveZoomControl(Bundle outState) {
+ outState.putBoolean(MapboxConstants.STATE_ZOOM_CONTROLS_ENABLED, isZoomControlsEnabled());
+ }
+
+ private void restoreZoomControl(Bundle savedInstanceState) {
+ setZoomControlsEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_CONTROLS_ENABLED));
+ }
+
+ /**
+ * <p>
+ * Enables or disables the compass. The compass is an icon on the map that indicates the
+ * direction of north on the map. When a user clicks
+ * the compass, the camera orients itself to its default orientation and fades away shortly
+ * after. If disabled, the compass will never be displayed.
+ * </p>
+ * By default, the compass is enabled.
+ *
+ * @param compassEnabled True to enable the compass; false to disable the compass.
+ */
+ public void setCompassEnabled(boolean compassEnabled) {
+ compassView.setEnabled(compassEnabled);
+ }
+
+ /**
+ * Returns whether the compass is enabled.
+ *
+ * @return True if the compass is enabled; false if the compass is disabled.
+ */
+ public boolean isCompassEnabled() {
+ return compassView.isEnabled();
+ }
+
+ /**
+ * <p>
+ * Sets the gravity of the compass view. Use this to change the corner of the map view that the
+ * compass is displayed in.
+ * </p>
+ * By default, the compass is in the top right corner.
+ *
+ * @param gravity One of the values from {@link Gravity}.
+ * @see Gravity
+ */
+ @UiThread
+ public void setCompassGravity(int gravity) {
+ setWidgetGravity(compassView, gravity);
+ }
+
+ /**
+ * Enables or disables fading of the compass when facing north.
+ * <p>
+ * By default this feature is enabled
+ * </p>
+ *
+ * @param compassFadeFacingNorth True to enable the fading animation; false to disable it
+ */
+ public void setCompassFadeFacingNorth(boolean compassFadeFacingNorth) {
+ compassView.fadeCompassViewFacingNorth(compassFadeFacingNorth);
+ }
+
+ /**
+ * Returns whether the compass performs a fading animation out when facing north.
+ *
+ * @return True if the compass will fade, false if it remains visible
+ */
+ public boolean isCompassFadeWhenFacingNorth() {
+ return compassView.isFadeCompassViewFacingNorth();
+ }
+
+ /**
+ * Returns the gravity value of the CompassView
+ *
+ * @return The gravity
+ */
+ public int getCompassGravity() {
+ return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).gravity;
+ }
+
+ /**
+ * Sets the margins of the compass view. Use this to change the distance of the compass from the
+ * map view edge.
+ *
+ * @param left The left margin in pixels.
+ * @param top The top margin in pixels.
+ * @param right The right margin in pixels.
+ * @param bottom The bottom margin in pixels.
+ */
+ @UiThread
+ public void setCompassMargins(int left, int top, int right, int bottom) {
+ setWidgetMargins(compassView, left, top, right, bottom);
+ }
+
+ /**
+ * Returns the left side margin of CompassView
+ *
+ * @return The left margin in pixels
+ */
+ public int getCompassMarginLeft() {
+ return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).leftMargin;
+ }
+
+ /**
+ * Returns the top side margin of CompassView
+ *
+ * @return The top margin in pixels
+ */
+ public int getCompassMarginTop() {
+ return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).topMargin;
+ }
+
+ /**
+ * Returns the right side margin of CompassView
+ *
+ * @return The right margin in pixels
+ */
+ public int getCompassMarginRight() {
+ return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).rightMargin;
+ }
+
+ /**
+ * Returns the bottom side margin of CompassView
+ *
+ * @return The bottom margin in pixels
+ */
+ public int getCompassMarginBottom() {
+ return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).bottomMargin;
+ }
+
+ void update(@NonNull CameraPosition cameraPosition) {
+ if (!isCompassEnabled()) {
+ return;
+ }
+
+ compassView.update(cameraPosition.bearing);
+ }
+
+ /**
+ * <p>
+ * Enables or disables the Mapbox logo.
+ * </p>
+ * By default, the logo is enabled.
+ *
+ * @param enabled True to enable the logo; false to disable the logo.
+ */
+ public void setLogoEnabled(boolean enabled) {
+ logoView.setVisibility(enabled ? View.VISIBLE : View.GONE);
+ }
+
+ /**
+ * Returns whether the logo is enabled.
+ *
+ * @return True if the logo is enabled; false if the logo is disabled.
+ */
+ public boolean isLogoEnabled() {
+ return logoView.getVisibility() == View.VISIBLE;
+ }
+
+ /**
+ * <p>
+ * Sets the gravity of the logo view. Use this to change the corner of the map view that the
+ * Mapbox logo is displayed in.
+ * </p>
+ * By default, the logo is in the bottom left corner.
+ *
+ * @param gravity One of the values from {@link Gravity}.
+ * @see Gravity
+ */
+ public void setLogoGravity(int gravity) {
+ setWidgetGravity(logoView, gravity);
+ }
+
+ /**
+ * Returns the gravity value of the logo
+ *
+ * @return The gravity
+ */
+ public int getLogoGravity() {
+ return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).gravity;
+ }
+
+ /**
+ * Sets the margins of the logo view. Use this to change the distance of the Mapbox logo from the
+ * map view edge.
+ *
+ * @param left The left margin in pixels.
+ * @param top The top margin in pixels.
+ * @param right The right margin in pixels.
+ * @param bottom The bottom margin in pixels.
+ */
+ public void setLogoMargins(int left, int top, int right, int bottom) {
+ setWidgetMargins(logoView, left, top, right, bottom);
+ }
+
+ /**
+ * Returns the left side margin of the logo
+ *
+ * @return The left margin in pixels
+ */
+ public int getLogoMarginLeft() {
+ return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).leftMargin;
+ }
+
+ /**
+ * Returns the top side margin of the logo
+ *
+ * @return The top margin in pixels
+ */
+ public int getLogoMarginTop() {
+ return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).topMargin;
+ }
+
+ /**
+ * Returns the right side margin of the logo
+ *
+ * @return The right margin in pixels
+ */
+ public int getLogoMarginRight() {
+ return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).rightMargin;
+ }
+
+ /**
+ * Returns the bottom side margin of the logo
+ *
+ * @return The bottom margin in pixels
+ */
+ public int getLogoMarginBottom() {
+ return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).bottomMargin;
+ }
+
+ /**
+ * <p>
+ * Enables or disables the attribution.
+ * </p>
+ * By default, the attribution is enabled.
+ *
+ * @param enabled True to enable the attribution; false to disable the attribution.
+ */
+ public void setAttributionEnabled(boolean enabled) {
+ attributionsView.setVisibility(enabled ? View.VISIBLE : View.GONE);
+ }
+
+ /**
+ * Returns whether the attribution is enabled.
+ *
+ * @return True if the attribution is enabled; false if the attribution is disabled.
+ */
+ public boolean isAttributionEnabled() {
+ return attributionsView.getVisibility() == View.VISIBLE;
+ }
+
+ /**
+ * <p>
+ * Sets the gravity of the attribution.
+ * </p>
+ * By default, the attribution is in the bottom left corner next to the Mapbox logo.
+ *
+ * @param gravity One of the values from {@link Gravity}.
+ * @see Gravity
+ */
+ public void setAttributionGravity(int gravity) {
+ setWidgetGravity(attributionsView, gravity);
+ }
+
+ /**
+ * Returns the gravity value of the logo
+ *
+ * @return The gravity
+ */
+ public int getAttributionGravity() {
+ return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).gravity;
+ }
+
+ /**
+ * Sets the margins of the attribution view.
+ *
+ * @param left The left margin in pixels.
+ * @param top The top margin in pixels.
+ * @param right The right margin in pixels.
+ * @param bottom The bottom margin in pixels.
+ */
+ public void setAttributionMargins(int left, int top, int right, int bottom) {
+ setWidgetMargins(attributionsView, left, top, right, bottom);
+ }
+
+ /**
+ * <p>
+ * Sets the tint of the attribution view. Use this to change the color of the attribution.
+ * </p>
+ * By default, the logo is tinted with the primary color of your theme.
+ *
+ * @param tintColor Color to tint the attribution.
+ */
+ public void setAttributionTintColor(@ColorInt int tintColor) {
+ // Check that the tint color being passed in isn't transparent.
+ if (Color.alpha(tintColor) == 0) {
+ ColorUtils.setTintList(attributionsView,
+ ContextCompat.getColor(attributionsView.getContext(), R.color.mapbox_blue));
+ } else {
+ ColorUtils.setTintList(attributionsView, tintColor);
+ }
+ }
+
+ /**
+ * Returns the left side margin of the attribution view.
+ *
+ * @return The left margin in pixels
+ */
+ public int getAttributionMarginLeft() {
+ return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).leftMargin;
+ }
+
+ /**
+ * Returns the top side margin of the attribution view.
+ *
+ * @return The top margin in pixels
+ */
+ public int getAttributionMarginTop() {
+ return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).topMargin;
+ }
+
+ /**
+ * Returns the right side margin of the attribution view.
+ *
+ * @return The right margin in pixels
+ */
+ public int getAttributionMarginRight() {
+ return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).rightMargin;
+ }
+
+ /**
+ * Returns the bottom side margin of the logo
+ *
+ * @return The bottom margin in pixels
+ */
+ public int getAttributionMarginBottom() {
+ return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).bottomMargin;
+ }
+
+ /**
+ * <p>
+ * Changes whether the user may rotate the map.
+ * </p>
+ * <p>
+ * This setting controls only user interactions with the map. If you set the value to false,
+ * you may still change the map location programmatically.
+ * </p>
+ * The default value is true.
+ *
+ * @param rotateGesturesEnabled If true, rotating is enabled.
+ */
+ public void setRotateGesturesEnabled(boolean rotateGesturesEnabled) {
+ if (rotateGestureChangeAllowed) {
+ this.rotateGesturesEnabled = rotateGesturesEnabled;
+ }
+ }
+
+ /**
+ * Returns whether the user may rotate the map.
+ *
+ * @return If true, rotating is enabled.
+ */
+ public boolean isRotateGesturesEnabled() {
+ return rotateGesturesEnabled;
+ }
+
+ void setRotateGestureChangeAllowed(boolean rotateGestureChangeAllowed) {
+ this.rotateGestureChangeAllowed = rotateGestureChangeAllowed;
+ }
+
+ boolean isRotateGestureChangeAllowed() {
+ return rotateGestureChangeAllowed;
+ }
+
+ /**
+ * <p>
+ * Changes whether the user may tilt the map.
+ * </p>
+ * <p>
+ * This setting controls only user interactions with the map. If you set the value to false,
+ * you may still change the map location programmatically.
+ * </p>
+ * The default value is true.
+ *
+ * @param tiltGesturesEnabled If true, tilting is enabled.
+ */
+ public void setTiltGesturesEnabled(boolean tiltGesturesEnabled) {
+ if (tiltGestureChangeAllowed) {
+ this.tiltGesturesEnabled = tiltGesturesEnabled;
+ }
+ }
+
+ /**
+ * Returns whether the user may tilt the map.
+ *
+ * @return If true, tilting is enabled.
+ */
+ public boolean isTiltGesturesEnabled() {
+ return tiltGesturesEnabled;
+ }
+
+ void setTiltGestureChangeAllowed(boolean tiltGestureChangeAllowed) {
+ this.tiltGestureChangeAllowed = tiltGestureChangeAllowed;
+ }
+
+ boolean isTiltGestureChangeAllowed() {
+ return tiltGestureChangeAllowed;
+ }
+
+ /**
+ * <p>
+ * Changes whether the user may zoom the map.
+ * </p>
+ * <p>
+ * This setting controls only user interactions with the map. If you set the value to false,
+ * you may still change the map location programmatically.
+ * </p>
+ * The default value is true.
+ *
+ * @param zoomGesturesEnabled If true, zooming is enabled.
+ */
+ public void setZoomGesturesEnabled(boolean zoomGesturesEnabled) {
+ if (zoomGestureChangeAllowed) {
+ this.zoomGesturesEnabled = zoomGesturesEnabled;
+ }
+ }
+
+ /**
+ * Returns whether the user may zoom the map.
+ *
+ * @return If true, zooming is enabled.
+ */
+ public boolean isZoomGesturesEnabled() {
+ return zoomGesturesEnabled;
+ }
+
+ void setZoomGestureChangeAllowed(boolean zoomGestureChangeAllowed) {
+ this.zoomGestureChangeAllowed = zoomGestureChangeAllowed;
+ }
+
+ boolean isZoomGestureChangeAllowed() {
+ return zoomGestureChangeAllowed;
+ }
+
+ /**
+ * <p>
+ * Sets whether the zoom controls are enabled.
+ * If enabled, the zoom controls are a pair of buttons
+ * (one for zooming in, one for zooming out) that appear on the screen.
+ * When pressed, they cause the camera to zoom in (or out) by one zoom level.
+ * If disabled, the zoom controls are not shown.
+ * </p>
+ * By default the zoom controls are enabled if the device is only single touch capable;
+ *
+ * @param zoomControlsEnabled If true, the zoom controls are enabled.
+ */
+ public void setZoomControlsEnabled(boolean zoomControlsEnabled) {
+ this.zoomControlsEnabled = zoomControlsEnabled;
+ }
+
+ /**
+ * Gets whether the zoom controls are enabled.
+ *
+ * @return If true, the zoom controls are enabled.
+ */
+ public boolean isZoomControlsEnabled() {
+ return zoomControlsEnabled;
+ }
+
+ /**
+ * Gets whether the markers are automatically deselected (and therefore, their infowindows
+ * closed) when a map tap is detected.
+ *
+ * @return If true, markers are deselected on a map tap.
+ */
+ public boolean isDeselectMarkersOnTap() {
+ return deselectMarkersOnTap;
+ }
+
+ /**
+ * Sets whether the markers are automatically deselected (and therefore, their infowindows
+ * closed) when a map tap is detected.
+ *
+ * @param deselectMarkersOnTap determines if markers should be deslected on tap
+ */
+ public void setDeselectMarkersOnTap(boolean deselectMarkersOnTap) {
+ this.deselectMarkersOnTap = deselectMarkersOnTap;
+ }
+
+ /**
+ * <p>
+ * Changes whether the user may scroll around the map.
+ * </p>
+ * <p>
+ * This setting controls only user interactions with the map. If you set the value to false,
+ * you may still change the map location programmatically.
+ * </p>
+ * The default value is true.
+ *
+ * @param scrollGesturesEnabled If true, scrolling is enabled.
+ */
+ public void setScrollGesturesEnabled(boolean scrollGesturesEnabled) {
+ if (scrollGestureChangeAllowed) {
+ this.scrollGesturesEnabled = scrollGesturesEnabled;
+ }
+ }
+
+ /**
+ * Returns whether the user may scroll around the map.
+ *
+ * @return If true, scrolling is enabled.
+ */
+ public boolean isScrollGesturesEnabled() {
+ return scrollGesturesEnabled;
+ }
+
+ void setScrollGestureChangeAllowed(boolean scrollGestureChangeAllowed) {
+ this.scrollGestureChangeAllowed = scrollGestureChangeAllowed;
+ }
+
+ boolean isScrollGestureChangeAllowed() {
+ return scrollGestureChangeAllowed;
+ }
+
+ /**
+ * <p>
+ * Sets the preference for whether all gestures should be enabled or disabled.
+ * </p>
+ * <p>
+ * This setting controls only user interactions with the map. If you set the value to false,
+ * you may still change the map location programmatically.
+ * </p>
+ * The default value is true.
+ *
+ * @param enabled If true, all gestures are available; otherwise, all gestures are disabled.
+ * @see #setZoomGesturesEnabled(boolean) )
+ * @see #setScrollGesturesEnabled(boolean)
+ * @see #setRotateGesturesEnabled(boolean)
+ * @see #setTiltGesturesEnabled(boolean)
+ */
+ public void setAllGesturesEnabled(boolean enabled) {
+ setScrollGesturesEnabled(enabled);
+ setRotateGesturesEnabled(enabled);
+ setTiltGesturesEnabled(enabled);
+ setZoomGesturesEnabled(enabled);
+ }
+
+ /**
+ * Sets the focal point used as center for a gesture
+ *
+ * @param focalPoint the focal point to be used.
+ */
+ public void setFocalPoint(@Nullable PointF focalPoint) {
+ this.userProvidedFocalPoint = focalPoint;
+ focalPointChangeListener.onFocalPointChanged(focalPoint);
+ }
+
+ /**
+ * Returns the gesture focal point
+ *
+ * @return The focal point
+ */
+ public PointF getFocalPoint() {
+ return userProvidedFocalPoint;
+ }
+
+ /**
+ * Returns the measured height of the MapView
+ *
+ * @return height in pixels
+ */
+ public float getHeight() {
+ return projection.getHeight();
+ }
+
+ /**
+ * Returns the measured width of the MapView
+ *
+ * @return widht in pixels
+ */
+ public float getWidth() {
+ return projection.getWidth();
+ }
+
+ float getPixelRatio() {
+ return pixelRatio;
+ }
+
+ /**
+ * Invalidates the ViewSettings instances shown on top of the MapView
+ */
+ public void invalidate() {
+ setLogoMargins(getLogoMarginLeft(), getLogoMarginTop(), getLogoMarginRight(), getLogoMarginBottom());
+ setCompassMargins(getCompassMarginLeft(), getCompassMarginTop(), getCompassMarginRight(), getCompassMarginBottom());
+ setAttributionMargins(getAttributionMarginLeft(), getAttributionMarginTop(), getAttributionMarginRight(),
+ getAttributionMarginBottom());
+ }
+
+ private void setWidgetGravity(@NonNull final View view, int gravity) {
+ FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) view.getLayoutParams();
+ layoutParams.gravity = gravity;
+ view.setLayoutParams(layoutParams);
+ }
+
+ private void setWidgetMargins(@NonNull final View view, int left, int top, int right, int bottom) {
+ int[] contentPadding = projection.getContentPadding();
+ FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) view.getLayoutParams();
+ left += contentPadding[0];
+ top += contentPadding[1];
+ right += contentPadding[2];
+ bottom += contentPadding[3];
+ layoutParams.setMargins(left, top, right, bottom);
+ view.setLayoutParams(layoutParams);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java
deleted file mode 100644
index 4478978853..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.mapbox.mapboxsdk.maps;
-
-/**
- * Settings for the overlain views of a MapboxMap. Used by UiSettings.
- */
-class ViewSettings {
-
- private boolean enabled;
- private int gravity;
- private int[] margins;
- private int tintColor;
-
- public ViewSettings() {
- margins = new int[4];
- }
-
- public boolean isEnabled() {
- return enabled;
- }
-
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
- public int getGravity() {
- return gravity;
- }
-
- public void setGravity(int gravity) {
- this.gravity = gravity;
- }
-
- public int[] getMargins() {
- return margins;
- }
-
- public void setMargins(int[] margins) {
- this.margins = margins;
- }
-
- public int getTintColor() {
- return tintColor;
- }
-
- public void setTintColor(int tintColor) {
- this.tintColor = tintColor;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
index 163c7a610a..dc4a21f2fe 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
@@ -27,133 +27,140 @@ import java.lang.ref.WeakReference;
*/
public final class CompassView extends ImageView implements Runnable {
- private static final long TIME_WAIT_IDLE = 500;
- private static final long TIME_FADE_ANIMATION = TIME_WAIT_IDLE;
- private static final long TIME_MAP_NORTH_ANIMATION = 150;
-
- private double direction = 0.0;
- private boolean fadeCompassViewFacingNorth = true;
- private ViewPropertyAnimatorCompat fadeAnimator;
-
- public CompassView(Context context) {
- super(context);
- initialize(context);
+ private static final long TIME_WAIT_IDLE = 500;
+ private static final long TIME_FADE_ANIMATION = TIME_WAIT_IDLE;
+ private static final long TIME_MAP_NORTH_ANIMATION = 150;
+
+ private double direction = 0.0;
+ private boolean fadeCompassViewFacingNorth = true;
+ private ViewPropertyAnimatorCompat fadeAnimator;
+
+ public CompassView(Context context) {
+ super(context);
+ initialize(context);
+ }
+
+ public CompassView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initialize(context);
+ }
+
+ public CompassView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ initialize(context);
+ }
+
+ private void initialize(Context context) {
+ setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.mapbox_compass_icon));
+ setContentDescription(getResources().getString(R.string.mapbox_compassContentDescription));
+ setEnabled(false);
+
+ // Layout params
+ float screenDensity = context.getResources().getDisplayMetrics().density;
+ ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams((int) (48 * screenDensity), (int) (48 * screenDensity));
+ setLayoutParams(lp);
+ }
+
+ // TODO refactor MapboxMap and replace with interface
+ public void setMapboxMap(@NonNull MapboxMap mapboxMap) {
+ setOnClickListener(new CompassClickListener(mapboxMap, this));
+ }
+
+ private void resetAnimation() {
+ if (fadeAnimator != null) {
+ fadeAnimator.cancel();
}
-
- public CompassView(Context context, AttributeSet attrs) {
- super(context, attrs);
- initialize(context);
+ fadeAnimator = null;
+ }
+
+ public boolean isHidden() {
+ return fadeCompassViewFacingNorth && isFacingNorth();
+ }
+
+ public boolean isFacingNorth() {
+ // increase range more than just 0.0
+ return direction >= 359.0 || direction <= 1.0;
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+ if (enabled && !isHidden()) {
+ resetAnimation();
+ setAlpha(1.0f);
+ setVisibility(View.VISIBLE);
+ } else {
+ resetAnimation();
+ setAlpha(0.0f);
+ setVisibility(View.INVISIBLE);
}
+ }
- public CompassView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- initialize(context);
- }
+ public void update(final double direction) {
+ this.direction = direction;
- private void initialize(Context context) {
- setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.compass));
- setContentDescription(getResources().getString(R.string.compassContentDescription));
- setEnabled(false);
-
- // Layout params
- float screenDensity = context.getResources().getDisplayMetrics().density;
- ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams((int) (48 * screenDensity), (int) (48 * screenDensity));
- setLayoutParams(lp);
+ if (!isEnabled()) {
+ return;
}
- public void setMapboxMap(@NonNull MapboxMap mapboxMap) {
- setOnClickListener(new CompassClickListener(mapboxMap, this));
+ if (isHidden()) {
+ if (getVisibility() == View.INVISIBLE || fadeAnimator != null) {
+ return;
+ }
+ postDelayed(this, TIME_WAIT_IDLE);
+ return;
+ } else {
+ resetAnimation();
+ setAlpha(1.0f);
+ setVisibility(View.VISIBLE);
}
- private void resetAnimation() {
- if (fadeAnimator != null) {
- fadeAnimator.cancel();
- }
- fadeAnimator = null;
- }
+ setRotation((float) direction);
+ }
- public boolean isHidden() {
- return fadeCompassViewFacingNorth && isFacingNorth();
- }
+ public void fadeCompassViewFacingNorth(boolean compassFadeFacingNorth) {
+ fadeCompassViewFacingNorth = compassFadeFacingNorth;
+ }
- public boolean isFacingNorth() {
- // increase range more than just 0.0
- return direction >= 359.0 || direction <= 1.0;
- }
+ public boolean isFadeCompassViewFacingNorth() {
+ return fadeCompassViewFacingNorth;
+ }
- @Override
- public void setEnabled(boolean enabled) {
- super.setEnabled(enabled);
- if (enabled && !isHidden()) {
- resetAnimation();
- setAlpha(1.0f);
- setVisibility(View.VISIBLE);
- } else {
- resetAnimation();
- setAlpha(0.0f);
- setVisibility(View.INVISIBLE);
+ @Override
+ public void run() {
+ if (isFacingNorth() && fadeCompassViewFacingNorth) {
+ resetAnimation();
+ setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ fadeAnimator = ViewCompat.animate(CompassView.this).alpha(0.0f).setDuration(TIME_FADE_ANIMATION);
+ fadeAnimator.setListener(new ViewPropertyAnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(View view) {
+ setLayerType(LAYER_TYPE_NONE, null);
+ setVisibility(View.INVISIBLE);
+ resetAnimation();
}
+ });
}
+ }
- public void update(final double direction) {
- this.direction = direction;
+ static class CompassClickListener implements View.OnClickListener {
- if (!isEnabled()) {
- return;
- }
+ private WeakReference<MapboxMap> mapboxMap;
+ private WeakReference<CompassView> compassView;
- if (isHidden()) {
- if (getVisibility() == View.INVISIBLE || fadeAnimator != null) {
- return;
- }
- postDelayed(this, TIME_WAIT_IDLE);
- return;
- } else {
- resetAnimation();
- setAlpha(1.0f);
- setVisibility(View.VISIBLE);
- }
-
- setRotation((float) direction);
- }
-
- public void fadeCompassViewFacingNorth(boolean compassFadeFacingNorth) {
- fadeCompassViewFacingNorth = compassFadeFacingNorth;
+ CompassClickListener(final MapboxMap mapboxMap, CompassView compassView) {
+ this.mapboxMap = new WeakReference<>(mapboxMap);
+ this.compassView = new WeakReference<>(compassView);
}
@Override
- public void run() {
- if (isFacingNorth() && fadeCompassViewFacingNorth) {
- resetAnimation();
- fadeAnimator = ViewCompat.animate(CompassView.this).alpha(0.0f).setDuration(TIME_FADE_ANIMATION).withLayer();
- fadeAnimator.setListener(new ViewPropertyAnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(View view) {
- setVisibility(View.INVISIBLE);
- resetAnimation();
- }
- });
- }
- }
-
- static class CompassClickListener implements View.OnClickListener {
-
- private WeakReference<MapboxMap> mapboxMap;
- private WeakReference<CompassView> compassView;
-
- CompassClickListener(final MapboxMap mapboxMap, CompassView compassView) {
- this.mapboxMap = new WeakReference<>(mapboxMap);
- this.compassView = new WeakReference<>(compassView);
- }
-
- @Override
- public void onClick(View view) {
- final MapboxMap mapboxMap = this.mapboxMap.get();
- final CompassView compassView = this.compassView.get();
- if (mapboxMap != null && compassView != null) {
- mapboxMap.resetNorth();
- compassView.postDelayed(compassView, TIME_WAIT_IDLE + TIME_MAP_NORTH_ANIMATION);
- }
- }
+ public void onClick(View view) {
+ final MapboxMap mapboxMap = this.mapboxMap.get();
+ final CompassView compassView = this.compassView.get();
+ if (mapboxMap != null && compassView != null) {
+ mapboxMap.resetNorth();
+ compassView.postDelayed(compassView, TIME_WAIT_IDLE + TIME_MAP_NORTH_ANIMATION);
+ }
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
index 45e0c4903e..c7dd867f2d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
@@ -4,7 +4,6 @@ import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Camera;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PointF;
@@ -44,728 +43,755 @@ import java.lang.ref.WeakReference;
*/
public class MyLocationView extends View {
- private MyLocationBehavior myLocationBehavior;
- private MapboxMap mapboxMap;
+ private MyLocationBehavior myLocationBehavior;
+ private MapboxMap mapboxMap;
- private Projection projection;
- private float[] projectedCoordinate = new float[2];
- private float projectedX;
- private float projectedY;
+ private Projection projection;
+ private float[] projectedCoordinate = new float[2];
+ private float projectedX;
+ private float projectedY;
- private float contentPaddingX;
- private float contentPaddingY;
+ private float contentPaddingX;
+ private float contentPaddingY;
- private LatLng latLng;
- private Location location;
- private long locationUpdateTimestamp;
- private float previousDirection;
+ private LatLng latLng;
+ private Location location;
+ private long locationUpdateTimestamp;
+ private float previousDirection;
- private float accuracy;
- private Paint accuracyPaint;
+ private float accuracy;
+ private Paint accuracyPaint;
- private ValueAnimator locationChangeAnimator;
- private ValueAnimator accuracyAnimator;
- private ValueAnimator directionAnimator;
+ private ValueAnimator locationChangeAnimator;
+ private ValueAnimator accuracyAnimator;
+ private ValueAnimator directionAnimator;
- private ValueAnimator.AnimatorUpdateListener invalidateSelfOnUpdateListener =
- new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- invalidate();
- }
- };
-
- private Drawable foregroundDrawable;
- private Drawable foregroundBearingDrawable;
- private Drawable backgroundDrawable;
+ private ValueAnimator.AnimatorUpdateListener invalidateSelfOnUpdateListener =
+ new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ invalidate();
+ }
+ };
- private Rect foregroundBounds;
- private Rect backgroundBounds;
+ private Drawable foregroundDrawable;
+ private Drawable foregroundBearingDrawable;
+ private Drawable backgroundDrawable;
- private int backgroundOffsetLeft;
- private int backgroundOffsetTop;
- private int backgroundOffsetRight;
- private int backgroundOffsetBottom;
+ private Rect foregroundBounds;
+ private Rect backgroundBounds;
- private Matrix matrix;
- private Camera camera;
- private PointF screenLocation;
+ private int backgroundOffsetLeft;
+ private int backgroundOffsetTop;
+ private int backgroundOffsetRight;
+ private int backgroundOffsetBottom;
- // camera vars
- private float bearing;
- private float tilt;
+ private Matrix matrix;
+ private Camera camera;
+ private PointF screenLocation;
- // Controls the compass update rate in milliseconds
- private static final int COMPASS_UPDATE_RATE_MS = 500;
+ // camera vars
+ private double tilt;
+ private double bearing;
+ private float magneticHeading;
- @MyLocationTracking.Mode
- private int myLocationTrackingMode;
+ // Controls the compass update rate in milliseconds
+ private static final int COMPASS_UPDATE_RATE_MS = 500;
- @MyBearingTracking.Mode
- private int myBearingTrackingMode;
+ @MyLocationTracking.Mode
+ private int myLocationTrackingMode;
- private GpsLocationListener userLocationListener;
- private CompassListener compassListener;
+ @MyBearingTracking.Mode
+ private int myBearingTrackingMode;
- public MyLocationView(Context context) {
- super(context);
- init(context);
- }
-
- public MyLocationView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(context);
- }
-
- public MyLocationView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init(context);
- }
-
- private void init(Context context) {
- if (isInEditMode()) {
- return;
- }
+ private GpsLocationListener userLocationListener;
+ private CompassListener compassListener;
- setEnabled(false);
+ public MyLocationView(Context context) {
+ super(context);
+ init(context);
+ }
- // setup LayoutParams
- ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT);
- setLayoutParams(lp);
+ public MyLocationView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
- matrix = new Matrix();
- camera = new Camera();
- camera.setLocation(0, 0, -1000);
- accuracyPaint = new Paint();
+ public MyLocationView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context);
+ }
- myLocationBehavior = new MyLocationBehaviorFactory().getBehavioralModel(MyLocationTracking.TRACKING_NONE);
- compassListener = new CompassListener(context);
+ private void init(Context context) {
+ if (isInEditMode()) {
+ return;
}
- public final void setForegroundDrawables(Drawable defaultDrawable, Drawable bearingDrawable) {
- if (defaultDrawable == null) {
- return;
- }
+ setEnabled(false);
- if (bearingDrawable == null) {
- // if user only provided one resource
- // use same for bearing mode
- bearingDrawable = defaultDrawable.getConstantState().newDrawable();
- }
+ // setup LayoutParams
+ ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ setLayoutParams(lp);
- if (backgroundDrawable == null) {
- // if the user didn't provide a background resource we will use the foreground resource instead,
- // we need to create a new drawable to handle tinting correctly
- backgroundDrawable = defaultDrawable.getConstantState().newDrawable();
- }
+ matrix = new Matrix();
+ camera = new Camera();
+ camera.setLocation(0, 0, -1000);
+ accuracyPaint = new Paint();
- if (defaultDrawable.getIntrinsicWidth() != bearingDrawable.getIntrinsicWidth() || defaultDrawable.getIntrinsicHeight() != bearingDrawable.getIntrinsicHeight()) {
- throw new RuntimeException("The dimensions from location and bearing drawables should be match");
- }
+ myLocationBehavior = new MyLocationBehaviorFactory().getBehavioralModel(MyLocationTracking.TRACKING_NONE);
+ compassListener = new CompassListener(context);
+ }
- foregroundDrawable = defaultDrawable;
- foregroundBearingDrawable = bearingDrawable;
+ public final void setForegroundDrawables(Drawable defaultDrawable, Drawable bearingDrawable) {
+ if (defaultDrawable == null) {
+ return;
+ }
- invalidateBounds();
+ if (bearingDrawable == null) {
+ // if user only provided one resource
+ // use same for bearing mode
+ bearingDrawable = defaultDrawable.getConstantState().newDrawable();
}
- public final void setForegroundDrawableTint(@ColorInt int color) {
- if (color != Color.TRANSPARENT) {
- if (foregroundDrawable != null) {
- foregroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
- }
- if (foregroundBearingDrawable != null) {
- foregroundBearingDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
- }
- }
- invalidate();
+ if (backgroundDrawable == null) {
+ // if the user didn't provide a background resource we will use the foreground resource instead,
+ // we need to create a new drawable to handle tinting correctly
+ backgroundDrawable = defaultDrawable.getConstantState().newDrawable();
}
- public final void setShadowDrawable(Drawable drawable) {
- setShadowDrawable(drawable, 0, 0, 0, 0);
+ if (defaultDrawable.getIntrinsicWidth() != bearingDrawable.getIntrinsicWidth()
+ || defaultDrawable.getIntrinsicHeight() != bearingDrawable.getIntrinsicHeight()) {
+ throw new RuntimeException("The dimensions from location and bearing drawables should be match");
}
- public final void setShadowDrawable(Drawable drawable, int left, int top, int right, int bottom) {
- if (drawable != null) {
- backgroundDrawable = drawable;
- }
+ foregroundDrawable = defaultDrawable;
+ foregroundBearingDrawable = bearingDrawable;
- backgroundOffsetLeft = left;
- backgroundOffsetTop = top;
- backgroundOffsetRight = right;
- backgroundOffsetBottom = bottom;
+ invalidateBounds();
+ }
- invalidateBounds();
+ public final void setForegroundDrawableTint(@ColorInt int color) {
+ if (foregroundDrawable != null) {
+ foregroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
-
- public final void setShadowDrawableTint(@ColorInt int color) {
- if (color != Color.TRANSPARENT) {
- if (backgroundDrawable == null) {
- return;
- }
- backgroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
- }
- invalidate();
+ if (foregroundBearingDrawable != null) {
+ foregroundBearingDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
+ invalidate();
+ }
- public final void setAccuracyTint(@ColorInt int color) {
- int alpha = accuracyPaint.getAlpha();
- accuracyPaint.setColor(color);
- accuracyPaint.setAlpha(alpha);
- invalidate();
- }
+ public final void setShadowDrawable(Drawable drawable) {
+ setShadowDrawable(drawable, 0, 0, 0, 0);
+ }
- public final void setAccuracyAlpha(@IntRange(from = 0, to = 255) int alpha) {
- accuracyPaint.setAlpha(alpha);
- invalidate();
+ public final void setShadowDrawable(Drawable drawable, int left, int top, int right, int bottom) {
+ if (drawable != null) {
+ backgroundDrawable = drawable;
}
- private void invalidateBounds() {
- if (backgroundDrawable == null || foregroundDrawable == null || foregroundBearingDrawable == null) {
- return;
- }
+ backgroundOffsetLeft = left;
+ backgroundOffsetTop = top;
+ backgroundOffsetRight = right;
+ backgroundOffsetBottom = bottom;
+
+ invalidateBounds();
+ }
- int backgroundWidth = backgroundDrawable.getIntrinsicWidth();
- int backgroundHeight = backgroundDrawable.getIntrinsicHeight();
- int horizontalOffset = backgroundOffsetLeft - backgroundOffsetRight;
- int verticalOffset = backgroundOffsetTop - backgroundOffsetBottom;
- backgroundBounds = new Rect(-backgroundWidth / 2 + horizontalOffset, -backgroundHeight / 2 + verticalOffset, backgroundWidth / 2 + horizontalOffset, backgroundHeight / 2 + verticalOffset);
- backgroundDrawable.setBounds(backgroundBounds);
+ public final void setShadowDrawableTint(@ColorInt int color) {
+ if (backgroundDrawable == null) {
+ return;
+ }
+ backgroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
+ invalidate();
+ }
- int foregroundWidth = foregroundDrawable.getIntrinsicWidth();
- int foregroundHeight = foregroundDrawable.getIntrinsicHeight();
- foregroundBounds = new Rect(-foregroundWidth / 2, -foregroundHeight / 2, foregroundWidth / 2, foregroundHeight / 2);
- foregroundDrawable.setBounds(foregroundBounds);
- foregroundBearingDrawable.setBounds(foregroundBounds);
+ public final void setAccuracyTint(@ColorInt int color) {
+ int alpha = accuracyPaint.getAlpha();
+ accuracyPaint.setColor(color);
+ accuracyPaint.setAlpha(alpha);
+ invalidate();
+ }
- // invoke a new draw
- invalidate();
+ public final void setAccuracyAlpha(@IntRange(from = 0, to = 255) int alpha) {
+ accuracyPaint.setAlpha(alpha);
+ invalidate();
+ }
+
+ private void invalidateBounds() {
+ if (backgroundDrawable == null || foregroundDrawable == null || foregroundBearingDrawable == null) {
+ return;
}
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
+ int backgroundWidth = backgroundDrawable.getIntrinsicWidth();
+ int backgroundHeight = backgroundDrawable.getIntrinsicHeight();
+ int horizontalOffset = backgroundOffsetLeft - backgroundOffsetRight;
+ int verticalOffset = backgroundOffsetTop - backgroundOffsetBottom;
+ backgroundBounds = new Rect(-backgroundWidth / 2 + horizontalOffset,
+ -backgroundHeight / 2 + verticalOffset, backgroundWidth / 2 + horizontalOffset, backgroundHeight / 2
+ + verticalOffset);
+ backgroundDrawable.setBounds(backgroundBounds);
- if (location == null || foregroundBounds == null || backgroundBounds == null || accuracyAnimator == null || screenLocation == null) {
- // Not ready yet
- return;
- }
+ int foregroundWidth = foregroundDrawable.getIntrinsicWidth();
+ int foregroundHeight = foregroundDrawable.getIntrinsicHeight();
+ foregroundBounds = new Rect(-foregroundWidth / 2, -foregroundHeight / 2, foregroundWidth / 2, foregroundHeight / 2);
+ foregroundDrawable.setBounds(foregroundBounds);
+ foregroundBearingDrawable.setBounds(foregroundBounds);
- final PointF pointF = screenLocation;
- float metersPerPixel = (float) projection.getMetersPerPixelAtLatitude(location.getLatitude());
- float accuracyPixels = (Float) accuracyAnimator.getAnimatedValue() / metersPerPixel / 2;
- float maxRadius = getWidth() / 2;
- accuracyPixels = accuracyPixels <= maxRadius ? accuracyPixels : maxRadius;
+ // invoke a new draw
+ invalidate();
+ }
- // reset
- matrix.reset();
- projectedCoordinate[0] = 0;
- projectedCoordinate[1] = 0;
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
- // put camera in position
- camera.save();
- camera.rotate(tilt, 0, 0);
- camera.getMatrix(matrix);
+ if (location == null || foregroundBounds == null || backgroundBounds == null || accuracyAnimator == null
+ || screenLocation == null) {
+ // Not ready yet
+ return;
+ }
- if (myBearingTrackingMode != MyBearingTracking.NONE && directionAnimator != null) {
- matrix.preRotate((Float) directionAnimator.getAnimatedValue());
- }
+ final PointF pointF = screenLocation;
+ float metersPerPixel = (float) projection.getMetersPerPixelAtLatitude(location.getLatitude());
+ float accuracyPixels = (Float) accuracyAnimator.getAnimatedValue() / metersPerPixel / 2;
+ float maxRadius = getWidth() / 2;
+ accuracyPixels = accuracyPixels <= maxRadius ? accuracyPixels : maxRadius;
- matrix.preTranslate(0, contentPaddingY);
- matrix.postTranslate(pointF.x, pointF.y - contentPaddingY);
+ // reset
+ matrix.reset();
+ projectedCoordinate[0] = 0;
+ projectedCoordinate[1] = 0;
- // concat our matrix on canvas
- canvas.concat(matrix);
+ // put camera in position
+ camera.save();
+ camera.rotate((float) tilt, 0, 0);
+ camera.getMatrix(matrix);
- // calculate focal point
- matrix.mapPoints(projectedCoordinate);
- projectedX = pointF.x - projectedCoordinate[0];
- projectedY = pointF.y - projectedCoordinate[1];
+ if (myBearingTrackingMode != MyBearingTracking.NONE && directionAnimator != null) {
+ matrix.preRotate((Float) directionAnimator.getAnimatedValue());
+ }
- // restore orientation from camera
- camera.restore();
+ matrix.preTranslate(0, contentPaddingY);
+ matrix.postTranslate(pointF.x, pointF.y - contentPaddingY);
- // draw circle
- canvas.drawCircle(0, 0, accuracyPixels, accuracyPaint);
+ // concat our matrix on canvas
+ canvas.concat(matrix);
- // draw shadow
- if (backgroundDrawable != null) {
- backgroundDrawable.draw(canvas);
- }
+ // calculate focal point
+ matrix.mapPoints(projectedCoordinate);
+ projectedX = pointF.x - projectedCoordinate[0];
+ projectedY = pointF.y - projectedCoordinate[1];
- // draw foreground
- if (myBearingTrackingMode == MyBearingTracking.NONE) {
- if (foregroundDrawable != null) {
- foregroundDrawable.draw(canvas);
- }
- } else if (foregroundBearingDrawable != null && foregroundBounds != null) {
- foregroundBearingDrawable.draw(canvas);
- }
- }
+ // restore orientation from camera
+ camera.restore();
- public void setTilt(@FloatRange(from = 0, to = 60.0f) double tilt) {
- this.tilt = (float) tilt;
- if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
- mapboxMap.getUiSettings().setFocalPoint(new PointF(getCenterX(), getCenterY()));
- }
- }
+ // draw circle
+ canvas.drawCircle(0, 0, accuracyPixels, accuracyPaint);
- public void setBearing(double bearing) {
- this.bearing = (float) bearing;
+ // draw shadow
+ if (backgroundDrawable != null) {
+ backgroundDrawable.draw(canvas);
}
- public void setCameraPosition(CameraPosition position) {
- setTilt(position.tilt);
- setBearing(position.bearing);
+ // draw foreground
+ if (myBearingTrackingMode == MyBearingTracking.NONE) {
+ if (foregroundDrawable != null) {
+ foregroundDrawable.draw(canvas);
+ }
+ } else if (foregroundBearingDrawable != null && foregroundBounds != null) {
+ foregroundBearingDrawable.draw(canvas);
}
-
- public void onResume() {
- if (myBearingTrackingMode == MyBearingTracking.COMPASS) {
- compassListener.onResume();
- }
- if (isEnabled()) {
- toggleGps(true);
- }
+ }
+
+ public void setTilt(@FloatRange(from = 0, to = 60.0f) double tilt) {
+ this.tilt = tilt;
+ if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
+ mapboxMap.getUiSettings().setFocalPoint(new PointF(getCenterX(), getCenterY()));
}
+ }
- public void onPause() {
- compassListener.onPause();
- toggleGps(false);
+ public void setBearing(double bearing) {
+ this.bearing = bearing;
+ if (myLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
+ if (myBearingTrackingMode == MyBearingTracking.GPS) {
+ if (location != null) {
+ setCompass(location.getBearing() - bearing);
+ }
+ } else if (myBearingTrackingMode == MyBearingTracking.COMPASS) {
+ setCompass(magneticHeading - bearing);
+ }
+ }
+ }
+
+ public void setCameraPosition(CameraPosition position) {
+ if (position != null) {
+ setTilt(position.tilt);
+ setBearing(position.bearing);
+ }
+ }
+
+ public void onStart() {
+ if (myBearingTrackingMode == MyBearingTracking.COMPASS) {
+ compassListener.onResume();
+ }
+ if (isEnabled()) {
+ toggleGps(true);
+ }
+ }
+
+ public void onStop() {
+ compassListener.onPause();
+ toggleGps(false);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ // cleanup to prevent memory leaks
+ if (locationChangeAnimator != null) {
+ locationChangeAnimator.cancel();
+ locationChangeAnimator = null;
}
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- // cleanup to prevent memory leaks
- if (locationChangeAnimator != null) {
- locationChangeAnimator.cancel();
- locationChangeAnimator = null;
- }
-
- if (accuracyAnimator != null) {
- accuracyAnimator.cancel();
- accuracyAnimator = null;
- }
-
- if (directionAnimator != null) {
- directionAnimator.cancel();
- directionAnimator = null;
- }
-
- if (userLocationListener != null) {
- LocationServices services = LocationServices.getLocationServices(getContext());
- services.removeLocationListener(userLocationListener);
- userLocationListener = null;
- }
+ if (accuracyAnimator != null) {
+ accuracyAnimator.cancel();
+ accuracyAnimator = null;
+ }
+
+ if (directionAnimator != null) {
+ directionAnimator.cancel();
+ directionAnimator = null;
+ }
+
+ if (userLocationListener != null) {
+ LocationServices services = LocationServices.getLocationServices(getContext());
+ services.removeLocationListener(userLocationListener);
+ userLocationListener = null;
+ }
+ }
+
+ public void update() {
+ if (isEnabled()) {
+ myLocationBehavior.invalidate();
+ } else {
+ setVisibility(View.INVISIBLE);
+ }
+ }
+
+ // TODO refactor MapboxMap out
+ public void setMapboxMap(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ this.projection = mapboxMap.getProjection();
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+ setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
+ toggleGps(enabled);
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable("superState", super.onSaveInstanceState());
+ bundle.putDouble("tilt", tilt);
+ return bundle;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ if (state instanceof Bundle) {
+ Bundle bundle = (Bundle) state;
+ tilt = bundle.getDouble("tilt");
+ state = bundle.getParcelable("superState");
+ }
+ super.onRestoreInstanceState(state);
+ }
+
+ /**
+ * Enabled / Disable GPS location updates along with updating the UI
+ *
+ * @param enableGps true if GPS is to be enabled, false if GPS is to be disabled
+ */
+ private void toggleGps(boolean enableGps) {
+ LocationServices locationServices = LocationServices.getLocationServices(getContext());
+ if (enableGps) {
+ // Set an initial location if one available
+ Location lastLocation = locationServices.getLastLocation();
+
+ if (lastLocation != null) {
+ setLocation(lastLocation);
+ }
+
+ if (userLocationListener == null) {
+ userLocationListener = new GpsLocationListener(this);
+ }
+
+ locationServices.addLocationListener(userLocationListener);
+ } else {
+ // Disable location and user dot
+ location = null;
+ locationServices.removeLocationListener(userLocationListener);
+ }
+
+ locationServices.toggleGPS(enableGps);
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ public void setLocation(Location location) {
+ if (location == null) {
+ this.location = null;
+ return;
+ }
+
+ this.location = location;
+ myLocationBehavior.updateLatLng(location);
+ }
+
+ public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) {
+ this.myBearingTrackingMode = myBearingTrackingMode;
+ if (myBearingTrackingMode == MyBearingTracking.COMPASS) {
+ compassListener.onResume();
+ } else {
+ compassListener.onPause();
+ if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
+ // always face north
+ setCompass(0);
+ } else {
+ myLocationBehavior.invalidate();
+ }
+ }
+ invalidate();
+ }
+
+ public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
+ MyLocationBehaviorFactory factory = new MyLocationBehaviorFactory();
+ myLocationBehavior = factory.getBehavioralModel(myLocationTrackingMode);
+
+ if (location != null) {
+ if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
+ // center map directly
+ mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(new LatLng(location)), 0, false /*linear interpolator*/,
+ false /*do not disable tracking*/, null);
+ } else {
+ // do not use interpolated location from tracking mode
+ latLng = null;
+ }
+ myLocationBehavior.updateLatLng(location);
+ }
+
+ this.myLocationTrackingMode = myLocationTrackingMode;
+ invalidate();
+ }
+
+ @MyLocationTracking.Mode
+ public int getMyLocationTrackingMode() {
+ return myLocationTrackingMode;
+ }
+
+
+ @MyBearingTracking.Mode
+ public int getMyBearingTrackingMode() {
+ return myBearingTrackingMode;
+ }
+
+ private void setCompass(double bearing) {
+ setCompass(bearing, 0 /* no animation */);
+ }
+
+ private void setCompass(double bearing, long duration) {
+ float oldDir = previousDirection;
+ if (directionAnimator != null) {
+ oldDir = (Float) directionAnimator.getAnimatedValue();
+ directionAnimator.end();
+ directionAnimator = null;
+ }
+
+ float newDir = (float) bearing;
+ float diff = oldDir - newDir;
+ if (diff > 180.0f) {
+ newDir += 360.0f;
+ } else if (diff < -180.0f) {
+ newDir -= 360.f;
}
+ previousDirection = newDir;
- public void update() {
- if (isEnabled()) {
- myLocationBehavior.invalidate();
- } else {
- setVisibility(View.INVISIBLE);
- }
- }
+ directionAnimator = ValueAnimator.ofFloat(oldDir, newDir);
+ directionAnimator.setDuration(duration);
+ directionAnimator.addUpdateListener(invalidateSelfOnUpdateListener);
+ directionAnimator.start();
+ }
- public void setMapboxMap(MapboxMap mapboxMap) {
- this.mapboxMap = mapboxMap;
- this.projection = mapboxMap.getProjection();
- }
+ public float getCenterX() {
+ return (getX() + getMeasuredWidth()) / 2 + contentPaddingX - projectedX;
+ }
- @Override
- public void setEnabled(boolean enabled) {
- super.setEnabled(enabled);
- setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
- toggleGps(enabled);
- }
+ public float getCenterY() {
+ return (getY() + getMeasuredHeight()) / 2 + contentPaddingY - projectedY;
+ }
- @Override
- protected Parcelable onSaveInstanceState() {
- Bundle bundle = new Bundle();
- bundle.putParcelable("superState", super.onSaveInstanceState());
- bundle.putFloat("tilt", tilt);
- return bundle;
- }
+ public void setContentPadding(int[] padding) {
+ contentPaddingX = (padding[0] - padding[2]) / 2;
+ contentPaddingY = (padding[1] - padding[3]) / 2;
+ }
+
+ private static class GpsLocationListener implements LocationListener {
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- if (state instanceof Bundle) {
- Bundle bundle = (Bundle) state;
- tilt = bundle.getFloat("tilt");
- state = bundle.getParcelable("superState");
- }
- super.onRestoreInstanceState(state);
+ private WeakReference<MyLocationView> userLocationView;
+
+ GpsLocationListener(MyLocationView myLocationView) {
+ userLocationView = new WeakReference<>(myLocationView);
}
/**
- * Enabled / Disable GPS location updates along with updating the UI
+ * Callback method for receiving location updates from LocationServices.
*
- * @param enableGps true if GPS is to be enabled, false if GPS is to be disabled
+ * @param location The new Location data
*/
- private void toggleGps(boolean enableGps) {
- LocationServices locationServices = LocationServices.getLocationServices(getContext());
- if (enableGps) {
- // Set an initial location if one available
- Location lastLocation = locationServices.getLastLocation();
+ @Override
+ public void onLocationChanged(Location location) {
+ MyLocationView locationView = userLocationView.get();
+ if (locationView != null) {
+ locationView.setLocation(location);
+ }
+ }
+ }
- if (lastLocation != null) {
- setLocation(lastLocation);
- }
+ private class CompassListener implements SensorEventListener {
- if (userLocationListener == null) {
- userLocationListener = new GpsLocationListener(this);
- }
+ private final SensorManager sensorManager;
- locationServices.addLocationListener(userLocationListener);
- } else {
- // Disable location and user dot
- location = null;
- locationServices.removeLocationListener(userLocationListener);
- }
+ private Sensor rotationVectorSensor;
+ float[] matrix = new float[9];
+ float[] orientation = new float[3];
- locationServices.toggleGPS(enableGps);
- }
+ // Compass data
+ private long compassUpdateNextTimestamp = 0;
- public Location getLocation() {
- return location;
+ CompassListener(Context context) {
+ sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+ rotationVectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
}
- public void setLocation(Location location) {
- if (location == null) {
- this.location = null;
- return;
- }
-
- this.location = location;
- myLocationBehavior.updateLatLng(location);
+ public void onResume() {
+ sensorManager.registerListener(this, rotationVectorSensor, SensorManager.SENSOR_DELAY_GAME);
}
- public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) {
- this.myBearingTrackingMode = myBearingTrackingMode;
- if (myBearingTrackingMode == MyBearingTracking.COMPASS) {
- compassListener.onResume();
- } else {
- compassListener.onPause();
- if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
- // always face north
- setCompass(0);
- }
- }
- invalidate();
+ public void onPause() {
+ sensorManager.unregisterListener(this, rotationVectorSensor);
}
- public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
- MyLocationBehaviorFactory factory = new MyLocationBehaviorFactory();
- myLocationBehavior = factory.getBehavioralModel(myLocationTrackingMode);
+ @Override
+ public void onSensorChanged(SensorEvent event) {
- if (location != null) {
- if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
- // center map directly
- mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(new LatLng(location)), 0, false /*linear interpolator*/, false /*do not disable tracking*/, null);
- } else {
- // do not use interpolated location from tracking mode
- latLng = null;
- }
- myLocationBehavior.updateLatLng(location);
- }
+ // check when the last time the compass was updated, return if too soon.
+ long currentTime = SystemClock.elapsedRealtime();
+ if (currentTime < compassUpdateNextTimestamp) {
+ return;
+ }
- this.myLocationTrackingMode = myLocationTrackingMode;
- invalidate();
- }
+ if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
- private void setCompass(float bearing) {
- float oldDir = previousDirection;
- if (directionAnimator != null) {
- oldDir = (Float) directionAnimator.getAnimatedValue();
- directionAnimator.end();
- directionAnimator = null;
- }
+ // calculate the rotation matrix
+ SensorManager.getRotationMatrixFromVector(matrix, event.values);
+ SensorManager.getOrientation(matrix, orientation);
- float newDir = bearing;
- float diff = oldDir - newDir;
- if (diff > 180.0f) {
- newDir += 360.0f;
- } else if (diff < -180.0f) {
- newDir -= 360.f;
+ magneticHeading = (float) Math.toDegrees(SensorManager.getOrientation(matrix, orientation)[0]);
+ if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
+ // Change the user location view orientation to reflect the device orientation
+ rotateCamera(magneticHeading);
+ setCompass(0, COMPASS_UPDATE_RATE_MS);
+ } else {
+ // Change compass direction
+ setCompass(magneticHeading - bearing, COMPASS_UPDATE_RATE_MS);
}
- previousDirection = newDir;
- directionAnimator = ValueAnimator.ofFloat(oldDir, newDir);
- directionAnimator.setDuration(COMPASS_UPDATE_RATE_MS);
- directionAnimator.addUpdateListener(invalidateSelfOnUpdateListener);
- directionAnimator.start();
+ compassUpdateNextTimestamp = currentTime + COMPASS_UPDATE_RATE_MS;
+ }
}
- public float getCenterX() {
- return (getX() + getMeasuredWidth()) / 2 + contentPaddingX - projectedX;
+ private void rotateCamera(float rotation) {
+ CameraPosition.Builder builder = new CameraPosition.Builder();
+ builder.bearing(rotation);
+ mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), COMPASS_UPDATE_RATE_MS,
+ false /*linear interpolator*/, false /*do not disable tracking*/, null);
}
- public float getCenterY() {
- return (getY() + getMeasuredHeight()) / 2 + contentPaddingY - projectedY;
- }
-
- public void setContentPadding(int[] padding) {
- contentPaddingX = (padding[0] - padding[2]) / 2;
- contentPaddingY = (padding[1] - padding[3]) / 2;
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
- private static class GpsLocationListener implements LocationListener {
+ }
- private WeakReference<MyLocationView> userLocationView;
+ private class MarkerCoordinateAnimatorListener implements ValueAnimator.AnimatorUpdateListener {
- GpsLocationListener(MyLocationView myLocationView) {
- userLocationView = new WeakReference<>(myLocationView);
- }
+ private MyLocationBehavior behavior;
+ private double fromLat;
+ private double fromLng;
+ private double toLat;
+ private double toLng;
- /**
- * Callback method for receiving location updates from LocationServices.
- *
- * @param location The new Location data
- */
- @Override
- public void onLocationChanged(Location location) {
- MyLocationView locationView = userLocationView.get();
- if (locationView != null) {
- locationView.setLocation(location);
- }
- }
+ private MarkerCoordinateAnimatorListener(MyLocationBehavior myLocationBehavior, LatLng from, LatLng to) {
+ behavior = myLocationBehavior;
+ fromLat = from.getLatitude();
+ fromLng = from.getLongitude();
+ toLat = to.getLatitude();
+ toLng = to.getLongitude();
}
- private class CompassListener implements SensorEventListener {
-
- private final SensorManager sensorManager;
-
- private Sensor rotationVectorSensor;
- float[] matrix = new float[9];
- float[] orientation = new float[3];
-
- private int currentDegree = 0;
-
- // Compass data
- private long compassUpdateNextTimestamp = 0;
-
- CompassListener(Context context) {
- sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
- rotationVectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
- }
-
- public void onResume() {
- sensorManager.registerListener(this, rotationVectorSensor, SensorManager.SENSOR_DELAY_GAME);
- }
-
- public void onPause() {
- sensorManager.unregisterListener(this, rotationVectorSensor);
- }
-
- @Override
- public void onSensorChanged(SensorEvent event) {
-
- // check when the last time the compass was updated, return if too soon.
- long currentTime = SystemClock.elapsedRealtime();
- if (currentTime < compassUpdateNextTimestamp) {
- return;
- }
-
- if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
-
- // calculate the rotation matrix
- SensorManager.getRotationMatrixFromVector(matrix, event.values);
- SensorManager.getOrientation(matrix, orientation);
-
- float magneticHeading = (float) Math.toDegrees(SensorManager.getOrientation(matrix, orientation)[0]);
- currentDegree = (int) (magneticHeading);
-
- // Change the user location view orientation to reflect the device orientation
- setCompass(currentDegree);
-
- if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
- rotateCamera();
- }
-
- compassUpdateNextTimestamp = currentTime + COMPASS_UPDATE_RATE_MS;
- }
- }
-
- private void rotateCamera() {
- CameraPosition.Builder builder = new CameraPosition.Builder();
- builder.bearing(currentDegree);
- mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), COMPASS_UPDATE_RATE_MS, false /*linear interpolator*/, false /*do not disable tracking*/, null);
- }
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float frac = animation.getAnimatedFraction();
+ double latitude = fromLat + (toLat - fromLat) * frac;
+ double longitude = fromLng + (toLng - fromLng) * frac;
+ behavior.updateLatLng(latitude, longitude);
+ update();
+ }
+ }
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- }
+ private class MyLocationBehaviorFactory {
+ MyLocationBehavior getBehavioralModel(@MyLocationTracking.Mode int mode) {
+ if (mode == MyLocationTracking.TRACKING_NONE) {
+ return new MyLocationShowBehavior();
+ } else {
+ return new MyLocationTrackingBehavior();
+ }
}
+ }
- private class MarkerCoordinateAnimatorListener implements ValueAnimator.AnimatorUpdateListener {
-
- private MyLocationBehavior behavior;
- private double fromLat;
- private double fromLng;
- private double toLat;
- private double toLng;
+ private abstract class MyLocationBehavior {
- private MarkerCoordinateAnimatorListener(MyLocationBehavior myLocationBehavior, LatLng from, LatLng to) {
- behavior = myLocationBehavior;
- fromLat = from.getLatitude();
- fromLng = from.getLongitude();
- toLat = to.getLatitude();
- toLng = to.getLongitude();
- }
+ void updateLatLng(@NonNull Location newLocation) {
+ location = newLocation;
+ }
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float frac = animation.getAnimatedFraction();
- double latitude = fromLat + (toLat - fromLat) * frac;
- double longitude = fromLng + (toLng - fromLng) * frac;
- behavior.updateLatLng(latitude, longitude);
- update();
- }
+ void updateLatLng(double lat, double lon) {
+ if (latLng != null) {
+ latLng.setLatitude(lat);
+ latLng.setLongitude(lon);
+ }
}
- private class MyLocationBehaviorFactory {
+ void updateAccuracy(@NonNull Location location) {
+ if (accuracyAnimator != null && accuracyAnimator.isRunning()) {
+ // use current accuracy as a starting point
+ accuracy = (Float) accuracyAnimator.getAnimatedValue();
+ accuracyAnimator.end();
+ }
- MyLocationBehavior getBehavioralModel(@MyLocationTracking.Mode int mode) {
- if (mode == MyLocationTracking.TRACKING_NONE) {
- return new MyLocationShowBehavior();
- } else {
- return new MyLocationTrackingBehavior();
- }
- }
+ accuracyAnimator = ValueAnimator.ofFloat(accuracy * 10, location.getAccuracy() * 10);
+ accuracyAnimator.setDuration(750);
+ accuracyAnimator.start();
+ accuracy = location.getAccuracy();
}
- private abstract class MyLocationBehavior {
+ abstract void invalidate();
+ }
- void updateLatLng(@NonNull Location newLocation) {
- location = newLocation;
- }
+ private class MyLocationTrackingBehavior extends MyLocationBehavior {
- void updateLatLng(double lat, double lon) {
- if (latLng != null) {
- latLng.setLatitude(lat);
- latLng.setLongitude(lon);
- }
- }
+ @Override
+ void updateLatLng(@NonNull Location location) {
+ super.updateLatLng(location);
+ if (latLng == null) {
+ // first location fix
+ latLng = new LatLng(location);
+ locationUpdateTimestamp = SystemClock.elapsedRealtime();
+ }
+
+ // updateLatLng timestamp
+ float previousUpdateTimeStamp = locationUpdateTimestamp;
+ locationUpdateTimestamp = SystemClock.elapsedRealtime();
+
+ // calculate animation duration
+ float animationDuration;
+ if (previousUpdateTimeStamp == 0) {
+ animationDuration = 0;
+ } else {
+ animationDuration = (locationUpdateTimestamp - previousUpdateTimeStamp) * 1.1f
+ /*make animation slightly longer*/;
+ }
+
+ // calculate interpolated location
+ latLng = new LatLng(location);
+ CameraPosition.Builder builder = new CameraPosition.Builder().target(latLng);
+
+ // add direction
+ if (myBearingTrackingMode == MyBearingTracking.GPS) {
+ if (location.hasBearing()) {
+ builder.bearing(location.getBearing());
+ }
+ setCompass(0, COMPASS_UPDATE_RATE_MS);
+ }
+
+ // accuracy
+ updateAccuracy(location);
+
+ // ease to new camera position with a linear interpolator
+ mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), (int) animationDuration,
+ false /*linear interpolator*/, false /*do not disable tracking*/, null);
+ }
- void updateAccuracy(@NonNull Location location) {
- if (accuracyAnimator != null && accuracyAnimator.isRunning()) {
- // use current accuracy as a starting point
- accuracy = (Float) accuracyAnimator.getAnimatedValue();
- accuracyAnimator.end();
- }
-
- accuracyAnimator = ValueAnimator.ofFloat(accuracy * 10, location.getAccuracy() * 10);
- accuracyAnimator.setDuration(750);
- accuracyAnimator.start();
- accuracy = location.getAccuracy();
- }
+ @Override
+ void invalidate() {
+ int[] mapPadding = mapboxMap.getPadding();
+ float x = (getWidth() + mapPadding[0] - mapPadding[2]) / 2 + contentPaddingX;
+ float y = (getHeight() - mapPadding[3] + mapPadding[1]) / 2 + contentPaddingY;
+ screenLocation = new PointF(x, y);
+ MyLocationView.this.invalidate();
+ }
+ }
- abstract void invalidate();
- }
-
- private class MyLocationTrackingBehavior extends MyLocationBehavior {
-
- @Override
- void updateLatLng(@NonNull Location location) {
- super.updateLatLng(location);
- if (latLng == null) {
- // first location fix
- latLng = new LatLng(location);
- locationUpdateTimestamp = SystemClock.elapsedRealtime();
- }
-
- // updateLatLng timestamp
- float previousUpdateTimeStamp = locationUpdateTimestamp;
- locationUpdateTimestamp = SystemClock.elapsedRealtime();
-
- // calculate animation duration
- float animationDuration;
- if (previousUpdateTimeStamp == 0) {
- animationDuration = 0;
- } else {
- animationDuration = (locationUpdateTimestamp - previousUpdateTimeStamp) * 1.1f /*make animation slightly longer*/;
- }
-
- // calculate interpolated location
- latLng = new LatLng(location);
- CameraPosition.Builder builder = new CameraPosition.Builder().target(latLng);
-
- // add direction
- if (myBearingTrackingMode == MyBearingTracking.GPS) {
- if (location.hasBearing()) {
- builder.bearing(location.getBearing());
- }
- setCompass(0);
- }
-
- // accuracy
- updateAccuracy(location);
-
- // ease to new camera position with a linear interpolator
- mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), (int) animationDuration, false /*linear interpolator*/, false /*do not disable tracking*/, null);
- }
+ private class MyLocationShowBehavior extends MyLocationBehavior {
- @Override
- void invalidate() {
- int[] mapPadding = mapboxMap.getPadding();
- float x = (getWidth() + mapPadding[0] - mapPadding[2]) / 2 + contentPaddingX;
- float y = (getHeight() - mapPadding[3] + mapPadding[1]) / 2 + contentPaddingY;
- screenLocation = new PointF(x, y);
- MyLocationView.this.invalidate();
- }
+ @Override
+ void updateLatLng(@NonNull final Location location) {
+ super.updateLatLng(location);
+ if (latLng == null) {
+ // first location update
+ latLng = new LatLng(location);
+ locationUpdateTimestamp = SystemClock.elapsedRealtime();
+ }
+
+ // update LatLng location
+ LatLng newLocation = new LatLng(location);
+
+ // update LatLng accuracy
+ updateAccuracy(location);
+
+ // calculate updateLatLng time + add some extra offset to improve animation
+ long previousUpdateTimeStamp = locationUpdateTimestamp;
+ locationUpdateTimestamp = SystemClock.elapsedRealtime();
+ long locationUpdateDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * 1.2f);
+
+ // animate changes
+ if (locationChangeAnimator != null) {
+ locationChangeAnimator.end();
+ locationChangeAnimator = null;
+ }
+
+ locationChangeAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
+ locationChangeAnimator.setDuration(locationUpdateDuration);
+ locationChangeAnimator.addUpdateListener(new MarkerCoordinateAnimatorListener(this,
+ latLng, newLocation
+ ));
+ locationChangeAnimator.start();
+ latLng = newLocation;
}
- private class MyLocationShowBehavior extends MyLocationBehavior {
-
- @Override
- void updateLatLng(@NonNull final Location location) {
- super.updateLatLng(location);
- if (latLng == null) {
- // first location update
- latLng = new LatLng(location);
- locationUpdateTimestamp = SystemClock.elapsedRealtime();
- }
-
- // update LatLng location
- LatLng newLocation = new LatLng(location);
-
- // update LatLng direction
- if (myBearingTrackingMode == MyBearingTracking.GPS && location.hasBearing()) {
- setCompass(location.getBearing() + bearing);
- }
-
- // update LatLng accuracy
- updateAccuracy(location);
-
- // calculate updateLatLng time + add some extra offset to improve animation
- long previousUpdateTimeStamp = locationUpdateTimestamp;
- locationUpdateTimestamp = SystemClock.elapsedRealtime();
- long locationUpdateDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * 1.2f);
-
- // animate changes
- if (locationChangeAnimator != null) {
- locationChangeAnimator.end();
- locationChangeAnimator = null;
- }
-
- locationChangeAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
- locationChangeAnimator.setDuration(locationUpdateDuration);
- locationChangeAnimator.addUpdateListener(new MarkerCoordinateAnimatorListener(this,
- latLng, newLocation
- ));
- locationChangeAnimator.start();
- latLng = newLocation;
- }
-
- @Override
- void invalidate() {
- if (latLng != null) {
- screenLocation = projection.toScreenLocation(latLng);
- }
- MyLocationView.this.invalidate();
- }
+ @Override
+ void invalidate() {
+ if (latLng != null) {
+ screenLocation = projection.toScreenLocation(latLng);
+ }
+ MyLocationView.this.invalidate();
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java
index 80bd1b3bef..6cfbfed733 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java
@@ -1,260 +1,298 @@
package com.mapbox.mapboxsdk.maps.widgets;
+import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.IntRange;
+import android.support.annotation.NonNull;
-import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.constants.MyLocationTracking;
+import com.mapbox.mapboxsdk.maps.FocalPointChangeListener;
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
+import com.mapbox.mapboxsdk.maps.Projection;
/**
* Settings to configure the visual appearance of the MyLocationView.
*/
public class MyLocationViewSettings {
- private MapView mapView;
- private MyLocationView myLocationView;
+ private Projection projection;
+ private MyLocationView myLocationView;
+ private FocalPointChangeListener focalPointChangeListener;
- //
- // State
- //
+ //
+ // State
+ //
- private boolean enabled;
+ private boolean enabled;
- //
- // Foreground
- //
+ //
+ // Foreground
+ //
- private Drawable foregroundDrawable;
- private Drawable foregroundBearingDrawable;
+ private Drawable foregroundDrawable;
+ private Drawable foregroundBearingDrawable;
- @ColorInt
- private int foregroundTintColor;
+ @ColorInt
+ private int foregroundTintColor;
- //
- // Background
- //
+ //
+ // Background
+ //
- private Drawable backgroundDrawable;
- private int[] backgroundOffset = new int[4];
+ private Drawable backgroundDrawable;
+ private int[] backgroundOffset = new int[4];
- @ColorInt
- private int backgroundTintColor;
+ @ColorInt
+ private int backgroundTintColor;
- //
- // Accuracy
- //
+ //
+ // Accuracy
+ //
- private int accuracyAlpha;
+ private int accuracyAlpha;
- @ColorInt
- private int accuracyTintColor;
+ @ColorInt
+ private int accuracyTintColor;
- //
- // Padding
- //
+ //
+ // Padding
+ //
- private int[] padding = new int[4];
+ private int[] padding = new int[4];
- /**
- * Creates an instance of MyLocationViewSettings
- *
- * @param mapView the MapView that hosts the MyLocationView
- * @param myLocationView the MyLocationView to apply the settings to
- * @see MyLocationView
- */
- public MyLocationViewSettings(MapView mapView, MyLocationView myLocationView) {
- this.mapView = mapView;
- this.myLocationView = myLocationView;
- }
+ /**
+ * Creates an instance of MyLocationViewSettings
+ * <p>
+ *
+ * @param myLocationView the MyLocationView to apply the settings to
+ * @param projection the MapView projection
+ * @param focalPointChangedListener the interface to be invoked when focal points changes
+ * @see MyLocationView
+ */
+ public MyLocationViewSettings(MyLocationView myLocationView, Projection projection, FocalPointChangeListener
+ focalPointChangedListener) {
+ this.myLocationView = myLocationView;
+ this.projection = projection;
+ this.focalPointChangeListener = focalPointChangedListener;
+ }
- /**
- * Returns if the MyLocationView is enabled
- *
- * @return true if MyLocationView is enabled,
- */
- public boolean isEnabled() {
- return enabled;
+ public void initialise(@NonNull MapboxMapOptions options) {
+ CameraPosition position = options.getCamera();
+ if (position != null && !position.equals(CameraPosition.DEFAULT)) {
+ setTilt(position.tilt);
}
-
- /**
- * Set the enabled state of MyLocationView
- *
- * @param enabled true shows the MyLocationView on the map
- */
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- myLocationView.setEnabled(enabled);
+ setForegroundDrawable(options.getMyLocationForegroundDrawable(), options.getMyLocationForegroundBearingDrawable());
+ setForegroundTintColor(options.getMyLocationForegroundTintColor());
+ setBackgroundDrawable(options.getMyLocationBackgroundDrawable(), options.getMyLocationBackgroundPadding());
+ setBackgroundTintColor(options.getMyLocationBackgroundTintColor());
+ setAccuracyAlpha(options.getMyLocationAccuracyAlpha());
+ setAccuracyTintColor(options.getMyLocationAccuracyTintColor());
+ }
+
+ /**
+ * Returns if the MyLocationView is enabled
+ *
+ * @return true if MyLocationView is enabled,
+ */
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ /**
+ * Set the enabled state of MyLocationView
+ *
+ * @param enabled true shows the MyLocationView on the map
+ */
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ myLocationView.setEnabled(enabled);
+ }
+
+ /**
+ * Set the foreground drawable of the MyLocationView
+ * <p>
+ * The foreground drawable is the image visible on screen
+ * </p>
+ *
+ * @param foregroundDrawable the drawable to show as foreground without bearing
+ * @param foregroundBearingDrawable the drawable to show as foreground when bearing is enabled
+ */
+ public void setForegroundDrawable(Drawable foregroundDrawable, Drawable foregroundBearingDrawable) {
+ this.foregroundDrawable = foregroundDrawable;
+ this.foregroundBearingDrawable = foregroundBearingDrawable;
+ myLocationView.setForegroundDrawables(foregroundDrawable, foregroundBearingDrawable);
+ }
+
+ /**
+ * Get the foreground drawable when bearing is disabled.
+ *
+ * @return the drawable used as foreground
+ */
+ public Drawable getForegroundDrawable() {
+ return foregroundDrawable;
+ }
+
+ /**
+ * Get the foreground drawable when bearing is enabled.
+ *
+ * @return the bearing drawable used as foreground
+ */
+ public Drawable getForegroundBearingDrawable() {
+ return foregroundBearingDrawable;
+ }
+
+ /**
+ * Set the foreground tint color.
+ * <p>
+ * The color will tint both the foreground and the bearing foreground drawable.
+ * </p>
+ *
+ * @param foregroundTintColor the color to tint the foreground drawable
+ */
+ public void setForegroundTintColor(@ColorInt int foregroundTintColor) {
+ this.foregroundTintColor = foregroundTintColor;
+ myLocationView.setForegroundDrawableTint(foregroundTintColor);
+ }
+
+ /**
+ * Get the foreground tint color.
+ *
+ * @return the foreground tint color
+ */
+ public int getForegroundTintColor() {
+ return foregroundTintColor;
+ }
+
+ /**
+ * Set the background drawable of MyLocationView
+ * <p>
+ * Padding can be added to provide an offset to the background
+ * </p>
+ *
+ * @param backgroundDrawable the drawable to show as background
+ * @param padding the padding added to the background
+ */
+ public void setBackgroundDrawable(Drawable backgroundDrawable, int[] padding) {
+ this.backgroundDrawable = backgroundDrawable;
+ this.backgroundOffset = padding;
+ if (padding != null && padding.length == 4) {
+ myLocationView.setShadowDrawable(backgroundDrawable, padding[0], padding[1], padding[2], padding[3]);
+ } else {
+ myLocationView.setShadowDrawable(backgroundDrawable);
}
-
- /**
- * Set the foreground drawable of the MyLocationView
- * <p>
- * The foreground drawable is the image visible on screen
- * </p>
- *
- * @param foregroundDrawable the drawable to show as foreground without bearing
- * @param foregroundBearingDrawable the drawable to show as foreground when bearing is enabled
- */
- public void setForegroundDrawable(Drawable foregroundDrawable, Drawable foregroundBearingDrawable) {
- this.foregroundDrawable = foregroundDrawable;
- this.foregroundBearingDrawable = foregroundBearingDrawable;
- myLocationView.setForegroundDrawables(foregroundDrawable, foregroundBearingDrawable);
- }
-
- /**
- * Get the foreground drawable when bearing is disabled.
- *
- * @return the drawable used as foreground
- */
- public Drawable getForegroundDrawable() {
- return foregroundDrawable;
- }
-
- /**
- * Get the foreground drawable when bearing is enabled.
- *
- * @return the bearing drawable used as foreground
- */
- public Drawable getForegroundBearingDrawable() {
- return foregroundBearingDrawable;
- }
-
- /**
- * Set the foreground tint color.
- * <p>
- * The color will tint both the foreground and the bearing foreground drawable.
- * </p>
- *
- * @param foregroundTintColor the color to tint the foreground drawable
- */
- public void setForegroundTintColor(@ColorInt int foregroundTintColor) {
- this.foregroundTintColor = foregroundTintColor;
- myLocationView.setForegroundDrawableTint(foregroundTintColor);
- }
-
- /**
- * Get the foreground tint color.
- *
- * @return the foreground tint color
- */
- public int getForegroundTintColor() {
- return foregroundTintColor;
- }
-
- /**
- * Set the background drawable of MyLocationView
- * <p>
- * Padding can be added to provide an offset to the background
- * </p>
- *
- * @param backgroundDrawable the drawable to show as background
- * @param padding the padding added to the background
- */
- public void setBackgroundDrawable(Drawable backgroundDrawable, int[] padding) {
- this.backgroundDrawable = backgroundDrawable;
- this.backgroundOffset = padding;
- if (padding != null && padding.length == 4) {
- myLocationView.setShadowDrawable(backgroundDrawable, padding[0], padding[1], padding[2], padding[3]);
- } else {
- myLocationView.setShadowDrawable(backgroundDrawable);
- }
- }
-
- /**
- * Get the background drawable of MyLocationView.
- *
- * @return the drawable used as background
- */
- public Drawable getBackgroundDrawable() {
- return backgroundDrawable;
- }
-
- /**
- * Set the background tint color.
- *
- * @param backgroundTintColor the color to tint the background
- */
- public void setBackgroundTintColor(@ColorInt int backgroundTintColor) {
- this.backgroundTintColor = backgroundTintColor;
- myLocationView.setShadowDrawableTint(backgroundTintColor);
- }
-
- /**
- * Get the background tint color.
- *
- * @return the background tint color
- */
- public int getBackgroundTintColor() {
- return backgroundTintColor;
- }
-
- /**
- * Get the background offset.
- *
- * @return the background offset
- */
- public int[] getBackgroundOffset() {
- return backgroundOffset;
- }
-
- /**
- * Set the MyLocationView padding.
- *
- * @param left the padding left of MyLocationView
- * @param top the padding top of MyLocationView
- * @param right the padding right of MyLocationView
- * @param bottom the padding bottom of MyLocaionView
- */
- public void setPadding(int left, int top, int right, int bottom) {
- padding = new int[]{left, top, right, bottom};
- myLocationView.setContentPadding(padding);
- mapView.invalidateContentPadding();
- }
-
- /**
- * Get the MyLocationView padding.
- *
- * @return an array describing the padding in a LTRB manner
- */
- public int[] getPadding() {
- return padding;
- }
-
- /**
- * Get the alpha value of the accuracy circle of MyLocationView
- *
- * @return the alpha value
- */
- public int getAccuracyAlpha() {
- return accuracyAlpha;
- }
-
- /**
- * Set the alpha value of the accuracy circle of MyLocationView
- *
- * @param accuracyAlpha the alpha value to set
- */
- public void setAccuracyAlpha(@IntRange(from = 0, to = 255) int accuracyAlpha) {
- this.accuracyAlpha = accuracyAlpha;
- myLocationView.setAccuracyAlpha(accuracyAlpha);
- }
-
- /**
- * Get the accuracy tint color of MyLocationView.
- *
- * @return the tint color used for accuracy
- */
- public int getAccuracyTintColor() {
- return accuracyTintColor;
- }
-
- /**
- * Set the accuracy tint color of MyLocationView.
- *
- * @param accuracyTintColor the accuracy tint color
- */
- public void setAccuracyTintColor(@ColorInt int accuracyTintColor) {
- this.accuracyTintColor = accuracyTintColor;
- myLocationView.setAccuracyTint(accuracyTintColor);
+ }
+
+ /**
+ * Get the background drawable of MyLocationView.
+ *
+ * @return the drawable used as background
+ */
+ public Drawable getBackgroundDrawable() {
+ return backgroundDrawable;
+ }
+
+ /**
+ * Set the background tint color.
+ *
+ * @param backgroundTintColor the color to tint the background
+ */
+ public void setBackgroundTintColor(@ColorInt int backgroundTintColor) {
+ this.backgroundTintColor = backgroundTintColor;
+ myLocationView.setShadowDrawableTint(backgroundTintColor);
+ }
+
+ /**
+ * Get the background tint color.
+ *
+ * @return the background tint color
+ */
+ public int getBackgroundTintColor() {
+ return backgroundTintColor;
+ }
+
+ /**
+ * Get the background offset.
+ *
+ * @return the background offset
+ */
+ public int[] getBackgroundOffset() {
+ return backgroundOffset;
+ }
+
+ /**
+ * Set the MyLocationView padding.
+ *
+ * @param left the padding left of MyLocationView
+ * @param top the padding top of MyLocationView
+ * @param right the padding right of MyLocationView
+ * @param bottom the padding bottom of MyLocaionView
+ */
+ public void setPadding(int left, int top, int right, int bottom) {
+ padding = new int[] {left, top, right, bottom};
+ myLocationView.setContentPadding(padding);
+ projection.invalidateContentPadding(padding);
+ invalidateFocalPointForTracking(myLocationView);
+ }
+
+ /**
+ * Get the MyLocationView padding.
+ *
+ * @return an array describing the padding in a LTRB manner
+ */
+ public int[] getPadding() {
+ return padding;
+ }
+
+ /**
+ * Get the alpha value of the accuracy circle of MyLocationView
+ *
+ * @return the alpha value
+ */
+ public int getAccuracyAlpha() {
+ return accuracyAlpha;
+ }
+
+ /**
+ * Set the alpha value of the accuracy circle of MyLocationView
+ *
+ * @param accuracyAlpha the alpha value to set
+ */
+ public void setAccuracyAlpha(@IntRange(from = 0, to = 255) int accuracyAlpha) {
+ this.accuracyAlpha = accuracyAlpha;
+ myLocationView.setAccuracyAlpha(accuracyAlpha);
+ }
+
+ /**
+ * Get the accuracy tint color of MyLocationView.
+ *
+ * @return the tint color used for accuracy
+ */
+ public int getAccuracyTintColor() {
+ return accuracyTintColor;
+ }
+
+ /**
+ * Set the accuracy tint color of MyLocationView.
+ *
+ * @param accuracyTintColor the accuracy tint color
+ */
+ public void setAccuracyTintColor(@ColorInt int accuracyTintColor) {
+ this.accuracyTintColor = accuracyTintColor;
+ myLocationView.setAccuracyTint(accuracyTintColor);
+ }
+
+ public void setTilt(double tilt) {
+ myLocationView.setTilt(tilt);
+ }
+
+ private void invalidateFocalPointForTracking(MyLocationView myLocationView) {
+ if (!(myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE)) {
+ focalPointChangeListener.onFocalPointChanged(new PointF(myLocationView.getCenterX(),
+ myLocationView.getCenterY()));
+ } else {
+ focalPointChangeListener.onFocalPointChanged(null);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityListener.java
index 0528194528..8f1046c79a 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityListener.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityListener.java
@@ -5,6 +5,6 @@ package com.mapbox.mapboxsdk.net;
*/
public interface ConnectivityListener {
- void onNetworkStateChanged(boolean connected);
+ void onNetworkStateChanged(boolean connected);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java
index 85695ec6c9..7c37569ae2 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java
@@ -7,90 +7,90 @@ import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.annotation.NonNull;
-import android.util.Log;
-import com.mapbox.mapboxsdk.MapboxAccountManager;
+import com.mapbox.mapboxsdk.Mapbox;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
+import timber.log.Timber;
+
/**
* Interface definition for a callback to be invoked when connectivity changes.
* Not public api.
*/
public class ConnectivityReceiver extends BroadcastReceiver {
- private static final String TAG = ConnectivityReceiver.class.getSimpleName();
- private static ConnectivityReceiver INSTANCE;
-
- /**
- * Get or create the singleton instance
- */
- public static synchronized ConnectivityReceiver instance(Context context) {
- if (INSTANCE == null) {
- //Register new instance
- INSTANCE = new ConnectivityReceiver();
- context.registerReceiver(INSTANCE, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
-
- //Add default listeners
- INSTANCE.addListener(new NativeConnectivityListener());
- }
-
- return INSTANCE;
+ private static ConnectivityReceiver INSTANCE;
+
+ /**
+ * Get or create the singleton instance
+ */
+ public static synchronized ConnectivityReceiver instance(Context context) {
+ if (INSTANCE == null) {
+ //Register new instance
+ INSTANCE = new ConnectivityReceiver();
+ context.registerReceiver(INSTANCE, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
+
+ //Add default listeners
+ INSTANCE.addListener(new NativeConnectivityListener());
}
- private List<ConnectivityListener> listeners = new CopyOnWriteArrayList<>();
+ return INSTANCE;
+ }
- private ConnectivityReceiver() {
- }
+ private List<ConnectivityListener> listeners = new CopyOnWriteArrayList<>();
- /**
- * @see BroadcastReceiver#onReceive(Context, Intent)
- */
- @Override
- public void onReceive(Context context, Intent intent) {
- boolean connected = isConnected(context);
- Log.v(TAG, "Connected: " + connected);
-
- //Loop over listeners
- for (ConnectivityListener listener : listeners) {
- listener.onNetworkStateChanged(connected);
- }
- }
+ private ConnectivityReceiver() {
+ }
- /**
- * Add a listener to be notified
- *
- * @param listener the listener to add
- */
- public void addListener(@NonNull ConnectivityListener listener) {
- listeners.add(listener);
- }
+ /**
+ * @see BroadcastReceiver#onReceive(Context, Intent)
+ */
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ boolean connected = isConnected(context);
+ Timber.v("Connected: " + connected);
- /**
- * Remove a listener
- *
- * @param listener the listener to remove
- */
- public void removeListener(@NonNull ConnectivityListener listener) {
- listeners.remove(listener);
+ //Loop over listeners
+ for (ConnectivityListener listener : listeners) {
+ listener.onNetworkStateChanged(connected);
}
-
- /**
- * Get current connectivity state
- *
- * @param context current Context
- * @return true if connected
- */
- public boolean isConnected(Context context) {
- Boolean connected = MapboxAccountManager.getInstance().isConnected();
- if (connected != null) {
- // Connectivity state overridden by app
- return connected;
- }
-
- ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
- return (activeNetwork != null && activeNetwork.isConnected());
+ }
+
+ /**
+ * Add a listener to be notified
+ *
+ * @param listener the listener to add
+ */
+ public void addListener(@NonNull ConnectivityListener listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * Remove a listener
+ *
+ * @param listener the listener to remove
+ */
+ public void removeListener(@NonNull ConnectivityListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * Get current connectivity state
+ *
+ * @param context current Context
+ * @return true if connected
+ */
+ public boolean isConnected(Context context) {
+ Boolean connected = Mapbox.isConnected();
+ if (connected != null) {
+ // Connectivity state overridden by app
+ return connected;
}
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
+ return (activeNetwork != null && activeNetwork.isConnected());
+ }
+
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/NativeConnectivityListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/NativeConnectivityListener.java
index 8b9307465c..76ce1de9d7 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/NativeConnectivityListener.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/NativeConnectivityListener.java
@@ -5,30 +5,30 @@ package com.mapbox.mapboxsdk.net;
*/
class NativeConnectivityListener implements ConnectivityListener {
- static {
- System.loadLibrary("mapbox-gl");
- }
+ static {
+ System.loadLibrary("mapbox-gl");
+ }
- private long nativePtr;
- private boolean invalidated;
+ private long nativePtr;
+ private boolean invalidated;
- NativeConnectivityListener(long nativePtr) {
- this.nativePtr = nativePtr;
- }
+ NativeConnectivityListener(long nativePtr) {
+ this.nativePtr = nativePtr;
+ }
- NativeConnectivityListener() {
- initialize();
- }
+ NativeConnectivityListener() {
+ initialize();
+ }
- @Override
- public void onNetworkStateChanged(boolean connected) {
- nativeOnConnectivityStateChanged(connected);
- }
+ @Override
+ public void onNetworkStateChanged(boolean connected) {
+ nativeOnConnectivityStateChanged(connected);
+ }
- protected native void nativeOnConnectivityStateChanged(boolean connected);
+ protected native void nativeOnConnectivityStateChanged(boolean connected);
- protected native void initialize();
+ protected native void initialize();
- @Override
- protected native void finalize() throws Throwable;
+ @Override
+ protected native void finalize() throws Throwable;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java
index 80d5ff7db0..beaea73024 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java
@@ -7,326 +7,298 @@ import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
-import android.util.Log;
-import com.mapbox.mapboxsdk.MapboxAccountManager;
+import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import java.io.File;
+import timber.log.Timber;
+
/**
* The offline manager is the main entry point for offline-related functionality.
* It'll help you list and create offline regions.
*/
public class OfflineManager {
- private final static String LOG_TAG = "OfflineManager";
-
- //
- // Static methods
- //
+ //
+ // Static methods
+ //
- static {
- System.loadLibrary("mapbox-gl");
- }
+ static {
+ System.loadLibrary("mapbox-gl");
+ }
- // Default database name
- private final static String DATABASE_NAME = "mbgl-offline.db";
+ // Default database name
+ private static final String DATABASE_NAME = "mbgl-offline.db";
- /*
- * The maximumCacheSize parameter is a limit applied to non-offline resources only,
- * i.e. resources added to the database for the "ambient use" caching functionality.
- * There is no size limit for offline resources.
- */
- private final static long DEFAULT_MAX_CACHE_SIZE = 50 * 1024 * 1024;
+ /*
+ * The maximumCacheSize parameter is a limit applied to non-offline resources only,
+ * i.e. resources added to the database for the "ambient use" caching functionality.
+ * There is no size limit for offline resources.
+ */
+ private static final long DEFAULT_MAX_CACHE_SIZE = 50 * 1024 * 1024;
- // Holds the pointer to JNI DefaultFileSource
- private long mDefaultFileSourcePtr = 0;
+ // Holds the pointer to JNI DefaultFileSource
+ private long mDefaultFileSourcePtr = 0;
- // Makes sure callbacks come back to the main thread
- private Handler handler;
+ // Makes sure callbacks come back to the main thread
+ private Handler handler;
- // This object is implemented as a singleton
- private static OfflineManager instance;
+ // This object is implemented as a singleton
+ private static OfflineManager instance;
+ /**
+ * This callback receives an asynchronous response containing a list of all
+ * {@link OfflineRegion} in the database, or an error message otherwise.
+ */
+ public interface ListOfflineRegionsCallback {
/**
- * This callback receives an asynchronous response containing a list of all
- * {@link OfflineRegion} in the database, or an error message otherwise.
+ * Receives the list of offline regions.
+ *
+ * @param offlineRegions the offline region array
*/
- public interface ListOfflineRegionsCallback {
- /**
- * Receives the list of offline regions.
- *
- * @param offlineRegions the offline region array
- */
- void onList(OfflineRegion[] offlineRegions);
-
- /**
- * Receives the error message.
- *
- * @param error the error message
- */
- void onError(String error);
- }
+ void onList(OfflineRegion[] offlineRegions);
/**
- * This callback receives an asynchronous response containing the newly created
- * {@link OfflineRegion} in the database, or an error message otherwise.
+ * Receives the error message.
+ *
+ * @param error the error message
*/
- public interface CreateOfflineRegionCallback {
- /**
- * Receives the newly created offline region.
- *
- * @param offlineRegion the offline region to create
- */
- void onCreate(OfflineRegion offlineRegion);
-
- /**
- * Receives the error message.
- *
- * @param error the error message to be shown
- */
- void onError(String error);
- }
-
- /*
- * Constructors
+ void onError(String error);
+ }
+
+ /**
+ * This callback receives an asynchronous response containing the newly created
+ * {@link OfflineRegion} in the database, or an error message otherwise.
+ */
+ public interface CreateOfflineRegionCallback {
+ /**
+ * Receives the newly created offline region.
+ *
+ * @param offlineRegion the offline region to create
*/
-
- private OfflineManager(Context context) {
- // Get a pointer to the DefaultFileSource instance
- String assetRoot = getDatabasePath(context);
- String cachePath = assetRoot + File.separator + DATABASE_NAME;
- mDefaultFileSourcePtr = createDefaultFileSource(cachePath, assetRoot, DEFAULT_MAX_CACHE_SIZE);
-
- if (MapboxAccountManager.getInstance() != null) {
- setAccessToken(mDefaultFileSourcePtr, MapboxAccountManager.getInstance().getAccessToken());
- }
-
- // Delete any existing previous ambient cache database
- deleteAmbientDatabase(context);
- }
-
- public static String getDatabasePath(Context context) {
- // Default value
- boolean setStorageExternal = MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL;
-
- try {
- // Try getting a custom value from the app Manifest
- ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(
- context.getPackageName(), PackageManager.GET_META_DATA);
- setStorageExternal = appInfo.metaData.getBoolean(
- MapboxConstants.KEY_META_DATA_SET_STORAGE_EXTERNAL,
- MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL);
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(LOG_TAG, "Failed to read the package metadata: " + e.getMessage());
- } catch (Exception e) {
- Log.e(LOG_TAG, "Failed to read the storage key: " + e.getMessage());
- }
-
- String databasePath = null;
- if (setStorageExternal && isExternalStorageReadable()) {
- try {
- // Try getting the external storage path
- databasePath = context.getExternalFilesDir(null).getAbsolutePath();
- } catch (NullPointerException e) {
- Log.e(LOG_TAG, "Failed to obtain the external storage path: " + e.getMessage());
- }
- }
-
- if (databasePath == null) {
- // Default to internal storage
- databasePath = context.getFilesDir().getAbsolutePath();
- }
-
- return databasePath;
- }
+ void onCreate(OfflineRegion offlineRegion);
/**
- * Checks if external storage is available to at least read. In order for this to work, make
- * sure you include &lt;uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /&gt;
- * (or WRITE_EXTERNAL_STORAGE) for API level &lt; 18 in your app Manifest.
- * <p>
- * Code from https://developer.android.com/guide/topics/data/data-storage.html#filesExternal
- * </p>
+ * Receives the error message.
*
- * @return true if external storage is readable
+ * @param error the error message to be shown
*/
- public static boolean isExternalStorageReadable() {
- String state = Environment.getExternalStorageState();
- if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
- return true;
- }
-
- Log.w(LOG_TAG, "External storage was requested but it isn't readable. For API level < 18"
- + " make sure you've requested READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE"
- + " permissions in your app Manifest (defaulting to internal storage).");
-
- return false;
+ void onError(String error);
+ }
+
+ /*
+ * Constructors
+ */
+ private OfflineManager(Context context) {
+ // Get a pointer to the DefaultFileSource instance
+ String assetRoot = getDatabasePath(context);
+ String cachePath = assetRoot + File.separator + DATABASE_NAME;
+ mDefaultFileSourcePtr = createDefaultFileSource(cachePath, assetRoot, DEFAULT_MAX_CACHE_SIZE);
+ setAccessToken(mDefaultFileSourcePtr, Mapbox.getAccessToken());
+
+ // Delete any existing previous ambient cache database
+ deleteAmbientDatabase(context);
+ }
+
+ public static String getDatabasePath(Context context) {
+ // Default value
+ boolean setStorageExternal = MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL;
+
+ try {
+ // Try getting a custom value from the app Manifest
+ ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(
+ context.getPackageName(), PackageManager.GET_META_DATA);
+ setStorageExternal = appInfo.metaData.getBoolean(
+ MapboxConstants.KEY_META_DATA_SET_STORAGE_EXTERNAL,
+ MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL);
+ } catch (PackageManager.NameNotFoundException exception) {
+ Timber.e("Failed to read the package metadata: ", exception);
+ } catch (Exception exception) {
+ Timber.e("Failed to read the storage key: ", exception);
}
- private void deleteAmbientDatabase(final Context context) {
- // Delete the file in a separate thread to avoid affecting the UI
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- String path = context.getCacheDir().getAbsolutePath() + File.separator + "mbgl-cache.db";
- File file = new File(path);
- if (file.exists()) {
- file.delete();
- Log.d(LOG_TAG, "Old ambient cache database deleted to save space: " + path);
- }
- } catch (Exception e) {
- Log.e(LOG_TAG, "Failed to delete old ambient cache database: " + e.getMessage());
- }
- }
- }).start();
+ String databasePath = null;
+ if (setStorageExternal && isExternalStorageReadable()) {
+ try {
+ // Try getting the external storage path
+ databasePath = context.getExternalFilesDir(null).getAbsolutePath();
+ } catch (NullPointerException exception) {
+ Timber.e("Failed to obtain the external storage path: ", exception);
+ }
}
- public static synchronized OfflineManager getInstance(Context context) {
- if (instance == null) {
- instance = new OfflineManager(context);
- }
-
- return instance;
+ if (databasePath == null) {
+ // Default to internal storage
+ databasePath = context.getFilesDir().getAbsolutePath();
}
- /**
- * Access token getter/setter
- *
- * @param accessToken the accessToken to be used by the offline manager.
- * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#start(Context, String)} ()}
- */
- @Deprecated
- public void setAccessToken(String accessToken) {
- setAccessToken(mDefaultFileSourcePtr, accessToken);
+ return databasePath;
+ }
+
+ /**
+ * Checks if external storage is available to at least read. In order for this to work, make
+ * sure you include &lt;uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /&gt;
+ * (or WRITE_EXTERNAL_STORAGE) for API level &lt; 18 in your app Manifest.
+ * <p>
+ * Code from https://developer.android.com/guide/topics/data/data-storage.html#filesExternal
+ * </p>
+ *
+ * @return true if external storage is readable
+ */
+ public static boolean isExternalStorageReadable() {
+ String state = Environment.getExternalStorageState();
+ if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
+ return true;
}
- /**
- * Get Access Token
- *
- * @return Access Token
- * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#getAccessToken()}
- */
- @Deprecated
- public String getAccessToken() {
- return getAccessToken(mDefaultFileSourcePtr);
- }
+ Timber.w("External storage was requested but it isn't readable. For API level < 18"
+ + " make sure you've requested READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE"
+ + " permissions in your app Manifest (defaulting to internal storage).");
+
+ return false;
+ }
- private Handler getHandler() {
- if (handler == null) {
- handler = new Handler(Looper.getMainLooper());
+ private void deleteAmbientDatabase(final Context context) {
+ // Delete the file in a separate thread to avoid affecting the UI
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ String path = context.getCacheDir().getAbsolutePath() + File.separator + "mbgl-cache.db";
+ File file = new File(path);
+ if (file.exists()) {
+ file.delete();
+ Timber.d("Old ambient cache database deleted to save space: " + path);
+ }
+ } catch (Exception exception) {
+ Timber.e("Failed to delete old ambient cache database: ", exception);
}
+ }
+ }).start();
+ }
- return handler;
+ public static synchronized OfflineManager getInstance(Context context) {
+ if (instance == null) {
+ instance = new OfflineManager(context);
}
- /**
- * Retrieve all regions in the offline database.
- * <p>
- * The query will be executed asynchronously and the results passed to the given
- * callback on the main thread.
- * </p>
- *
- * @param callback the callback to be invoked
- */
- public void listOfflineRegions(@NonNull final ListOfflineRegionsCallback callback) {
- listOfflineRegions(mDefaultFileSourcePtr, new ListOfflineRegionsCallback() {
- @Override
- public void onList(final OfflineRegion[] offlineRegions) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- callback.onList(offlineRegions);
- }
- });
- }
-
- @Override
- public void onError(final String error) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- callback.onError(error);
- }
- });
- }
- });
- }
+ return instance;
+ }
- /**
- * Create an offline region in the database.
- * <p>
- * When the initial database queries have completed, the provided callback will be
- * executed on the main thread.
- * </p>
- * <p>
- * Note that the resulting region will be in an inactive download state; to begin
- * downloading resources, call `OfflineRegion.setDownloadState(DownloadState.STATE_ACTIVE)`,
- * optionally registering an `OfflineRegionObserver` beforehand.
- * </p>
- *
- * @param definition the offline region definition
- * @param metadata the metadata in bytes
- * @param callback the callback to be invoked
- */
- public void createOfflineRegion(
- @NonNull OfflineRegionDefinition definition,
- @NonNull byte[] metadata,
- @NonNull final CreateOfflineRegionCallback callback) {
-
- createOfflineRegion(mDefaultFileSourcePtr, definition, metadata, new CreateOfflineRegionCallback() {
- @Override
- public void onCreate(final OfflineRegion offlineRegion) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- callback.onCreate(offlineRegion);
- }
- });
- }
-
- @Override
- public void onError(final String error) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- callback.onError(error);
- }
- });
- }
- });
+ private Handler getHandler() {
+ if (handler == null) {
+ handler = new Handler(Looper.getMainLooper());
}
- /*
- * Changing or bypassing this limit without permission from Mapbox is prohibited
- * by the Mapbox Terms of Service.
- */
- public void setOfflineMapboxTileCountLimit(long limit) {
- setOfflineMapboxTileCountLimit(mDefaultFileSourcePtr, limit);
- }
+ return handler;
+ }
+
+ /**
+ * Retrieve all regions in the offline database.
+ * <p>
+ * The query will be executed asynchronously and the results passed to the given
+ * callback on the main thread.
+ * </p>
+ *
+ * @param callback the callback to be invoked
+ */
+ public void listOfflineRegions(@NonNull final ListOfflineRegionsCallback callback) {
+ listOfflineRegions(mDefaultFileSourcePtr, new ListOfflineRegionsCallback() {
+ @Override
+ public void onList(final OfflineRegion[] offlineRegions) {
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onList(offlineRegions);
+ }
+ });
+ }
+
+ @Override
+ public void onError(final String error) {
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onError(error);
+ }
+ });
+ }
+ });
+ }
+
+ /**
+ * Create an offline region in the database.
+ * <p>
+ * When the initial database queries have completed, the provided callback will be
+ * executed on the main thread.
+ * </p>
+ * <p>
+ * Note that the resulting region will be in an inactive download state; to begin
+ * downloading resources, call `OfflineRegion.setDownloadState(DownloadState.STATE_ACTIVE)`,
+ * optionally registering an `OfflineRegionObserver` beforehand.
+ * </p>
+ *
+ * @param definition the offline region definition
+ * @param metadata the metadata in bytes
+ * @param callback the callback to be invoked
+ */
+ public void createOfflineRegion(
+ @NonNull OfflineRegionDefinition definition,
+ @NonNull byte[] metadata,
+ @NonNull final CreateOfflineRegionCallback callback) {
+
+ createOfflineRegion(mDefaultFileSourcePtr, definition, metadata, new CreateOfflineRegionCallback() {
+ @Override
+ public void onCreate(final OfflineRegion offlineRegion) {
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onCreate(offlineRegion);
+ }
+ });
+ }
+
+ @Override
+ public void onError(final String error) {
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onError(error);
+ }
+ });
+ }
+ });
+ }
+ /*
+ * Changing or bypassing this limit without permission from Mapbox is prohibited
+ * by the Mapbox Terms of Service.
+ */
+ public void setOfflineMapboxTileCountLimit(long limit) {
+ setOfflineMapboxTileCountLimit(mDefaultFileSourcePtr, limit);
+ }
- /*
- * Native methods
- */
- private native long createDefaultFileSource(
- String cachePath, String assetRoot, long maximumCacheSize);
+ /*
+ * Native methods
+ */
+ private native long createDefaultFileSource(
+ String cachePath, String assetRoot, long maximumCacheSize);
- private native void setAccessToken(long defaultFileSourcePtr, String accessToken);
+ private native void setAccessToken(long defaultFileSourcePtr, String accessToken);
- private native String getAccessToken(long defaultFileSourcePtr);
+ private native String getAccessToken(long defaultFileSourcePtr);
- private native void listOfflineRegions(
- long defaultFileSourcePtr, ListOfflineRegionsCallback callback);
+ private native void listOfflineRegions(
+ long defaultFileSourcePtr, ListOfflineRegionsCallback callback);
- private native void createOfflineRegion(
- long defaultFileSourcePtr, OfflineRegionDefinition definition,
- byte[] metadata, CreateOfflineRegionCallback callback);
+ private native void createOfflineRegion(
+ long defaultFileSourcePtr, OfflineRegionDefinition definition,
+ byte[] metadata, CreateOfflineRegionCallback callback);
- private native void setOfflineMapboxTileCountLimit(
- long defaultFileSourcePtr, long limit);
+ private native void setOfflineMapboxTileCountLimit(
+ long defaultFileSourcePtr, long limit);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java
index f52f20083a..a4d8a646d3 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java
@@ -4,7 +4,8 @@ import android.os.Handler;
import android.os.Looper;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
-import android.util.Log;
+
+import timber.log.Timber;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -16,416 +17,418 @@ import java.lang.annotation.RetentionPolicy;
*/
public class OfflineRegion {
- private final static String LOG_TAG = "OfflineRegion";
+ //
+ // Static methods
+ //
- //
- // Static methods
- //
+ static {
+ System.loadLibrary("mapbox-gl");
+ }
- static {
- System.loadLibrary("mapbox-gl");
- }
+ // Parent OfflineManager
+ private OfflineManager offlineManager;
- // Parent OfflineManager
- private OfflineManager offlineManager;
+ // Members
+ private long mId = 0;
+ private OfflineRegionDefinition mDefinition = null;
- // Members
- private long mId = 0;
- private OfflineRegionDefinition mDefinition = null;
+ /**
+ * Arbitrary binary region metadata. The contents are opaque to the SDK implementation;
+ * it just stores and retrieves a byte[]. Check the `OfflineActivity` in the TestApp
+ * for a sample implementation that uses JSON to store an offline region name.
+ */
+ private byte[] mMetadata = null;
- /**
- * Arbitrary binary region metadata. The contents are opaque to the SDK implementation;
- * it just stores and retrieves a byte[]. Check the `OfflineActivity` in the TestApp
- * for a sample implementation that uses JSON to store an offline region name.
- */
- private byte[] mMetadata = null;
+ // Holds the pointer to JNI OfflineRegion
+ private long mOfflineRegionPtr = 0;
- // Holds the pointer to JNI OfflineRegion
- private long mOfflineRegionPtr = 0;
-
- // Makes sure callbacks come back to the main thread
- private Handler handler;
+ // Makes sure callbacks come back to the main thread
+ private Handler handler;
+ /**
+ * A region can have a single observer, which gets notified whenever a change
+ * to the region's status occurs.
+ */
+ public interface OfflineRegionObserver {
/**
- * A region can have a single observer, which gets notified whenever a change
- * to the region's status occurs.
+ * Implement this method to be notified of a change in the status of an
+ * offline region. Status changes include any change in state of the members
+ * of OfflineRegionStatus.
+ * <p>
+ * This method will be executed on the main thread.
+ * </p>
+ *
+ * @param status the changed status
*/
- public interface OfflineRegionObserver {
- /**
- * Implement this method to be notified of a change in the status of an
- * offline region. Status changes include any change in state of the members
- * of OfflineRegionStatus.
- * <p>
- * This method will be executed on the main thread.
- * </p>
- *
- * @param status the changed status
- */
- void onStatusChanged(OfflineRegionStatus status);
-
- /**
- * Implement this method to be notified of errors encountered while downloading
- * regional resources. Such errors may be recoverable; for example the implementation
- * will attempt to re-request failed resources based on an exponential backoff
- * algorithm, or when it detects that network access has been restored.
- * <p>
- * This method will be executed on the main thread.
- * </p>
- *
- * @param error the offline region error message
- */
- void onError(OfflineRegionError error);
-
- /*
- * Implement this method to be notified when the limit on the number of Mapbox
- * tiles stored for offline regions has been reached.
- *
- * Once the limit has been reached, the SDK will not download further offline
- * tiles from Mapbox APIs until existing tiles have been removed. Contact your
- * Mapbox sales representative to raise the limit.
- *
- * This limit does not apply to non-Mapbox tile sources.
- *
- * This method will be executed on the main thread.
- */
- void mapboxTileCountLimitExceeded(long limit);
- }
+ void onStatusChanged(OfflineRegionStatus status);
/**
- * This callback receives an asynchronous response containing the {@link OfflineRegionStatus}
- * of the offline region, or a {@link String} error message otherwise.
+ * Implement this method to be notified of errors encountered while downloading
+ * regional resources. Such errors may be recoverable; for example the implementation
+ * will attempt to re-request failed resources based on an exponential backoff
+ * algorithm, or when it detects that network access has been restored.
+ * <p>
+ * This method will be executed on the main thread.
+ * </p>
+ *
+ * @param error the offline region error message
*/
- public interface OfflineRegionStatusCallback {
- /**
- * Receives the status
- *
- * @param status the offline region status
- */
- void onStatus(OfflineRegionStatus status);
-
- /**
- * Receives the error message
- *
- * @param error the error message
- */
- void onError(String error);
- }
+ void onError(OfflineRegionError error);
+ /*
+ * Implement this method to be notified when the limit on the number of Mapbox
+ * tiles stored for offline regions has been reached.
+ *
+ * Once the limit has been reached, the SDK will not download further offline
+ * tiles from Mapbox APIs until existing tiles have been removed. Contact your
+ * Mapbox sales representative to raise the limit.
+ *
+ * This limit does not apply to non-Mapbox tile sources.
+ *
+ * This method will be executed on the main thread.
+ */
+ void mapboxTileCountLimitExceeded(long limit);
+ }
+
+ /**
+ * This callback receives an asynchronous response containing the {@link OfflineRegionStatus}
+ * of the offline region, or a {@link String} error message otherwise.
+ */
+ public interface OfflineRegionStatusCallback {
/**
- * This callback receives an asynchronous response containing a notification when
- * an offline region has been deleted, or a {@link String} error message otherwise.
+ * Receives the status
+ *
+ * @param status the offline region status
*/
- public interface OfflineRegionDeleteCallback {
- /**
- * Receives the delete notification
- */
- void onDelete();
-
- /**
- * Receives the error message
- *
- * @param error the error message
- */
- void onError(String error);
- }
+ void onStatus(OfflineRegionStatus status);
/**
- * This callback receives an asynchronous response containing the newly update
- * OfflineMetadata in the database, or an error message otherwise.
+ * Receives the error message
+ *
+ * @param error the error message
*/
- public interface OfflineRegionUpdateMetadataCallback {
- /**
- * Receives the newly update offline region metadata.
- *
- * @param metadata the offline metadata to u[date
- */
- void onUpdate(byte[] metadata);
-
- /**
- * Receives the error message.
- *
- * @param error the error message to be shown
- */
- void onError(String error);
- }
-
+ void onError(String error);
+ }
+
+ /**
+ * This callback receives an asynchronous response containing a notification when
+ * an offline region has been deleted, or a {@link String} error message otherwise.
+ */
+ public interface OfflineRegionDeleteCallback {
/**
- * A region is either inactive (not downloading, but previously-downloaded
- * resources are available for use), or active (resources are being downloaded
- * or will be downloaded, if necessary, when network access is available).
- * <p>
- * This state is independent of whether or not the complete set of resources
- * is currently available for offline use. To check if that is the case, use
- * `OfflineRegionStatus.isComplete()`.
- * </p>
+ * Receives the delete notification
*/
-
- @IntDef({STATE_INACTIVE, STATE_ACTIVE})
- @Retention(RetentionPolicy.SOURCE)
- public @interface DownloadState {
- }
-
- public static final int STATE_INACTIVE = 0;
- public static final int STATE_ACTIVE = 1;
-
- // Keep track of the region state
- private int state = STATE_INACTIVE;
-
- private boolean deliverInactiveMessages = false;
+ void onDelete();
/**
- * Gets whether or not the `OfflineRegionObserver` will continue to deliver messages even if
- * the region state has been set as STATE_INACTIVE.
+ * Receives the error message
*
- * @return true if delivering inactive messages
+ * @param error the error message
*/
- public boolean isDeliveringInactiveMessages() {
- return deliverInactiveMessages;
- }
+ void onError(String error);
+ }
+
+ /**
+ * This callback receives an asynchronous response containing the newly update
+ * OfflineMetadata in the database, or an error message otherwise.
+ */
+ public interface OfflineRegionUpdateMetadataCallback {
+ /**
+ * Receives the newly update offline region metadata.
+ *
+ * @param metadata the offline metadata to u[date
+ */
+ void onUpdate(byte[] metadata);
/**
- * When set true, the `OfflineRegionObserver` will continue to deliver messages even if
- * the region state has been set as STATE_INACTIVE (operations happen asynchronously). If set
- * false, the client won't be notified of further messages.
+ * Receives the error message.
*
- * @param deliverInactiveMessages true if it should deliver inactive messages
+ * @param error the error message to be shown
*/
- public void setDeliverInactiveMessages(boolean deliverInactiveMessages) {
- this.deliverInactiveMessages = deliverInactiveMessages;
+ void onError(String error);
+ }
+
+ /**
+ * A region is either inactive (not downloading, but previously-downloaded
+ * resources are available for use), or active (resources are being downloaded
+ * or will be downloaded, if necessary, when network access is available).
+ * <p>
+ * This state is independent of whether or not the complete set of resources
+ * is currently available for offline use. To check if that is the case, use
+ * `OfflineRegionStatus.isComplete()`.
+ * </p>
+ */
+
+ @IntDef( {STATE_INACTIVE, STATE_ACTIVE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DownloadState {
+ }
+
+ public static final int STATE_INACTIVE = 0;
+ public static final int STATE_ACTIVE = 1;
+
+ // Keep track of the region state
+ private int state = STATE_INACTIVE;
+
+ private boolean deliverInactiveMessages = false;
+
+ /**
+ * Gets whether or not the `OfflineRegionObserver` will continue to deliver messages even if
+ * the region state has been set as STATE_INACTIVE.
+ *
+ * @return true if delivering inactive messages
+ */
+ public boolean isDeliveringInactiveMessages() {
+ return deliverInactiveMessages;
+ }
+
+ /**
+ * When set true, the `OfflineRegionObserver` will continue to deliver messages even if
+ * the region state has been set as STATE_INACTIVE (operations happen asynchronously). If set
+ * false, the client won't be notified of further messages.
+ *
+ * @param deliverInactiveMessages true if it should deliver inactive messages
+ */
+ public void setDeliverInactiveMessages(boolean deliverInactiveMessages) {
+ this.deliverInactiveMessages = deliverInactiveMessages;
+ }
+
+ private boolean deliverMessages() {
+ if (state == STATE_ACTIVE) {
+ return true;
}
-
- private boolean deliverMessages() {
- if (state == STATE_ACTIVE) return true;
- if (isDeliveringInactiveMessages()) return true;
- return false;
+ if (isDeliveringInactiveMessages()) {
+ return true;
}
+ return false;
+ }
- /*
- * Constructor
- */
-
- private OfflineRegion() {
- // For JNI use only, to create a new offline region, use
- // OfflineManager.createOfflineRegion() instead.
- }
+ /*
+ * Constructor
+ */
- /*
- * Getters
- */
+ private OfflineRegion() {
+ // For JNI use only, to create a new offline region, use
+ // OfflineManager.createOfflineRegion() instead.
+ }
- public long getID() {
- return mId;
- }
+ /*
+ * Getters
+ */
- public OfflineRegionDefinition getDefinition() {
- return mDefinition;
- }
+ public long getID() {
+ return mId;
+ }
- public byte[] getMetadata() {
- return mMetadata;
- }
+ public OfflineRegionDefinition getDefinition() {
+ return mDefinition;
+ }
- private Handler getHandler() {
- if (handler == null) {
- handler = new Handler(Looper.getMainLooper());
- }
+ public byte[] getMetadata() {
+ return mMetadata;
+ }
- return handler;
+ private Handler getHandler() {
+ if (handler == null) {
+ handler = new Handler(Looper.getMainLooper());
}
- /**
- * Register an observer to be notified when the state of the region changes.
- *
- * @param observer the observer to be notified
- */
- public void setObserver(@NonNull final OfflineRegionObserver observer) {
- setOfflineRegionObserver(new OfflineRegionObserver() {
+ return handler;
+ }
+
+ /**
+ * Register an observer to be notified when the state of the region changes.
+ *
+ * @param observer the observer to be notified
+ */
+ public void setObserver(@NonNull final OfflineRegionObserver observer) {
+ setOfflineRegionObserver(new OfflineRegionObserver() {
+ @Override
+ public void onStatusChanged(final OfflineRegionStatus status) {
+ if (deliverMessages()) {
+ getHandler().post(new Runnable() {
@Override
- public void onStatusChanged(final OfflineRegionStatus status) {
- if (deliverMessages()) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- observer.onStatusChanged(status);
- }
- });
- }
+ public void run() {
+ observer.onStatusChanged(status);
}
+ });
+ }
+ }
+ @Override
+ public void onError(final OfflineRegionError error) {
+ if (deliverMessages()) {
+ getHandler().post(new Runnable() {
@Override
- public void onError(final OfflineRegionError error) {
- if (deliverMessages()) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- observer.onError(error);
- }
- });
- }
+ public void run() {
+ observer.onError(error);
}
+ });
+ }
+ }
+ @Override
+ public void mapboxTileCountLimitExceeded(final long limit) {
+ if (deliverMessages()) {
+ getHandler().post(new Runnable() {
@Override
- public void mapboxTileCountLimitExceeded(final long limit) {
- if (deliverMessages()) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- observer.mapboxTileCountLimitExceeded(limit);
- }
- });
- }
+ public void run() {
+ observer.mapboxTileCountLimitExceeded(limit);
}
+ });
+ }
+ }
+ });
+ }
+
+ /**
+ * Pause or resume downloading of regional resources.
+ *
+ * @param state the download state
+ */
+ public void setDownloadState(@DownloadState int state) {
+ this.state = state;
+ setOfflineRegionDownloadState(state);
+ }
+
+ /**
+ * Retrieve the current status of the region. The query will be executed
+ * asynchronously and the results passed to the given callback which will be
+ * executed on the main thread.
+ *
+ * @param callback the callback to invoked.
+ */
+ public void getStatus(@NonNull final OfflineRegionStatusCallback callback) {
+ getOfflineRegionStatus(new OfflineRegionStatusCallback() {
+ @Override
+ public void onStatus(final OfflineRegionStatus status) {
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onStatus(status);
+ }
});
- }
-
- /**
- * Pause or resume downloading of regional resources.
- *
- * @param state the download state
- */
- public void setDownloadState(@DownloadState int state) {
- this.state = state;
- setOfflineRegionDownloadState(state);
- }
-
- /**
- * Retrieve the current status of the region. The query will be executed
- * asynchronously and the results passed to the given callback which will be
- * executed on the main thread.
- *
- * @param callback the callback to invoked.
- */
- public void getStatus(@NonNull final OfflineRegionStatusCallback callback) {
- getOfflineRegionStatus(new OfflineRegionStatusCallback() {
- @Override
- public void onStatus(final OfflineRegionStatus status) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- callback.onStatus(status);
- }
- });
- }
-
- @Override
- public void onError(final String error) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- callback.onError(error);
- }
- });
- }
+ }
+
+ @Override
+ public void onError(final String error) {
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onError(error);
+ }
});
- }
-
- /**
- * Remove an offline region from the database and perform any resources evictions
- * necessary as a result.
- * <p>
- * Eviction works by removing the least-recently requested resources not also required
- * by other regions, until the database shrinks below a certain size.
- * </p>
- * <p>
- * When the operation is complete or encounters an error, the given callback will be
- * executed on the main thread.
- * </p>
- * <p>
- * After you call this method, you may not call any additional methods on this object.
- * </p>
- *
- * @param callback the callback to be invoked
- */
- public void delete(@NonNull final OfflineRegionDeleteCallback callback) {
- deleteOfflineRegion(new OfflineRegionDeleteCallback() {
- @Override
- public void onDelete() {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- callback.onDelete();
- OfflineRegion.this.finalize();
- }
- });
- }
-
- @Override
- public void onError(final String error) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- callback.onError(error);
- }
- });
- }
+ }
+ });
+ }
+
+ /**
+ * Remove an offline region from the database and perform any resources evictions
+ * necessary as a result.
+ * <p>
+ * Eviction works by removing the least-recently requested resources not also required
+ * by other regions, until the database shrinks below a certain size.
+ * </p>
+ * <p>
+ * When the operation is complete or encounters an error, the given callback will be
+ * executed on the main thread.
+ * </p>
+ * <p>
+ * After you call this method, you may not call any additional methods on this object.
+ * </p>
+ *
+ * @param callback the callback to be invoked
+ */
+ public void delete(@NonNull final OfflineRegionDeleteCallback callback) {
+ deleteOfflineRegion(new OfflineRegionDeleteCallback() {
+ @Override
+ public void onDelete() {
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onDelete();
+ OfflineRegion.this.finalize();
+ }
});
- }
-
- /**
- * Update an offline region metadata from the database.
- * <p>
- * When the operation is complete or encounters an error, the given callback will be
- * executed on the main thread.
- * </p>
- * <p>
- * After you call this method, you may not call any additional methods on this object.
- * </p>
- *
- * @param callback the callback to be invoked
- */
- public void updateMetadata(@NonNull final byte[] bytes, @NonNull final OfflineRegionUpdateMetadataCallback callback) {
- updateOfflineRegionMetadata(bytes, new OfflineRegionUpdateMetadataCallback() {
- @Override
- public void onUpdate(final byte[] metadata) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- mMetadata = metadata;
- callback.onUpdate(metadata);
- }
- });
- }
-
- @Override
- public void onError(final String error) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- callback.onError(error);
- }
- });
- }
+ }
+
+ @Override
+ public void onError(final String error) {
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onError(error);
+ }
});
+ }
+ });
+ }
+
+ /**
+ * Update an offline region metadata from the database.
+ * <p>
+ * When the operation is complete or encounters an error, the given callback will be
+ * executed on the main thread.
+ * </p>
+ * <p>
+ * After you call this method, you may not call any additional methods on this object.
+ * </p>
+ *
+ * @param callback the callback to be invoked
+ */
+ public void updateMetadata(@NonNull final byte[] bytes, @NonNull final OfflineRegionUpdateMetadataCallback callback) {
+ updateOfflineRegionMetadata(bytes, new OfflineRegionUpdateMetadataCallback() {
+ @Override
+ public void onUpdate(final byte[] metadata) {
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ mMetadata = metadata;
+ callback.onUpdate(metadata);
+ }
+ });
+ }
+
+ @Override
+ public void onError(final String error) {
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onError(error);
+ }
+ });
+ }
+ });
+ }
+
+ @Override
+ protected void finalize() {
+ try {
+ super.finalize();
+ destroyOfflineRegion();
+ } catch (Throwable throwable) {
+ Timber.e("Failed to finalize OfflineRegion: " + throwable.getMessage());
}
+ }
- @Override
- protected void finalize() {
- try {
- super.finalize();
- destroyOfflineRegion();
- } catch (Throwable throwable) {
- Log.e(LOG_TAG, "Failed to finalize OfflineRegion: " + throwable.getMessage());
- }
- }
-
- /*
- * Native methods
- */
+ /*
+ * Native methods
+ */
- private native void destroyOfflineRegion();
+ private native void destroyOfflineRegion();
- private native void setOfflineRegionObserver(
- OfflineRegionObserver observerCallback);
+ private native void setOfflineRegionObserver(
+ OfflineRegionObserver observerCallback);
- private native void setOfflineRegionDownloadState(
- @DownloadState int offlineRegionDownloadState);
+ private native void setOfflineRegionDownloadState(
+ @DownloadState int offlineRegionDownloadState);
- private native void getOfflineRegionStatus(
- OfflineRegionStatusCallback statusCallback);
+ private native void getOfflineRegionStatus(
+ OfflineRegionStatusCallback statusCallback);
- private native void deleteOfflineRegion(
- OfflineRegionDeleteCallback deleteCallback);
+ private native void deleteOfflineRegion(
+ OfflineRegionDeleteCallback deleteCallback);
- private native void updateOfflineRegionMetadata(byte[] metadata, OfflineRegionUpdateMetadataCallback callback);
+ private native void updateOfflineRegionMetadata(byte[] metadata, OfflineRegionUpdateMetadataCallback callback);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionDefinition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionDefinition.java
index 0e7fb38e1c..a21ff0a443 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionDefinition.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionDefinition.java
@@ -2,7 +2,7 @@ package com.mapbox.mapboxsdk.offline;
/**
* This is the interface that all Offline Region definitions have to implement.
- *
+ * <p>
* For the present, a tile pyramid is the only type of offline region.
*/
public interface OfflineRegionDefinition {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionError.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionError.java
index e7a57379c5..60c4a8661c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionError.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionError.java
@@ -10,44 +10,47 @@ import java.lang.annotation.RetentionPolicy;
*/
public class OfflineRegionError {
- /**
- * Error code, as a string, self-explanatory.
- */
- @StringDef({REASON_SUCCESS, REASON_NOT_FOUND, REASON_SERVER, REASON_CONNECTION, REASON_OTHER})
- @Retention(RetentionPolicy.SOURCE)
- public @interface ErrorReason {}
-
- public static final String REASON_SUCCESS = "REASON_SUCCESS";
- public static final String REASON_NOT_FOUND = "REASON_NOT_FOUND";
- public static final String REASON_SERVER = "REASON_SERVER";
- public static final String REASON_CONNECTION = "REASON_CONNECTION";
- public static final String REASON_OTHER = "REASON_OTHER";
-
- private @ErrorReason String reason;
-
- /**
- /* An error message from the request handler, e.g. a server message or a system message
- /* informing the user about the reason for the failure.
- */
- private String message;
-
- /*
- * Constructors
- */
-
- private OfflineRegionError() {
- // For JNI use only
- }
-
- /*
- * Getters
- */
-
- public @ErrorReason String getReason() {
- return reason;
- }
-
- public String getMessage() {
- return message;
- }
+ /**
+ * Error code, as a string, self-explanatory.
+ */
+ @StringDef( {REASON_SUCCESS, REASON_NOT_FOUND, REASON_SERVER, REASON_CONNECTION, REASON_OTHER})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ErrorReason {
+ }
+
+ public static final String REASON_SUCCESS = "REASON_SUCCESS";
+ public static final String REASON_NOT_FOUND = "REASON_NOT_FOUND";
+ public static final String REASON_SERVER = "REASON_SERVER";
+ public static final String REASON_CONNECTION = "REASON_CONNECTION";
+ public static final String REASON_OTHER = "REASON_OTHER";
+
+ @ErrorReason
+ private String reason;
+
+ /**
+ * /* An error message from the request handler, e.g. a server message or a system message
+ * /* informing the user about the reason for the failure.
+ */
+ private String message;
+
+ /*
+ * Constructors
+ */
+
+ private OfflineRegionError() {
+ // For JNI use only
+ }
+
+ /*
+ * Getters
+ */
+
+ @ErrorReason
+ public String getReason() {
+ return reason;
+ }
+
+ public String getMessage() {
+ return message;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java
index 48609a13bb..11f2da132d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java
@@ -4,101 +4,103 @@ package com.mapbox.mapboxsdk.offline;
* A region's status includes its active/inactive state as well as counts
* of the number of resources that have completed downloading, their total
* size in bytes, and the total number of resources that are required.
- *
+ * <p>
* Note that the total required size in bytes is not currently available. A
* future API release may provide an estimate of this number.
*/
public class OfflineRegionStatus {
- @OfflineRegion.DownloadState private int downloadState = OfflineRegion.STATE_INACTIVE;
-
- /**
- * The number of resources (inclusive of tiles) that have been fully downloaded
- * and are ready for offline access.
- */
- private long completedResourceCount = 0;
-
- /**
- * The cumulative size, in bytes, of all resources (inclusive of tiles) that have
- * been fully downloaded.
- */
- private long completedResourceSize = 0;
-
- /**
- * The number of tiles that have been fully downloaded and are ready for
- * offline access.
- */
- private long completedTileCount = 0;
-
- /**
- * The cumulative size, in bytes, of all tiles that have been fully downloaded.
- */
- private long completedTileSize = 0;
-
- /**
- * The number of resources that are known to be required for this region. See the
- * documentation for `requiredResourceCountIsPrecise` for an important caveat
- * about this number.
- */
- private long requiredResourceCount = 0;
-
- /**
- * This property is true when the value of requiredResourceCount is a precise
- * count of the number of required resources, and false when it is merely a lower
- * bound.
- *
- * Specifically, it is false during early phases of an offline download. Once
- * style and tile sources have been downloaded, it is possible to calculate the
- * precise number of required resources, at which point it is set to true.
- */
- private boolean requiredResourceCountIsPrecise = true;
-
- /*
- * Use setObserver(OfflineRegionObserver observer) to obtain a OfflineRegionStatus object.
- */
-
- private OfflineRegionStatus() {
- // For JNI use only
- }
-
- /*
- * Is the region complete?
- */
-
- public boolean isComplete() {
- return (completedResourceCount == requiredResourceCount);
- }
-
- /*
- * Getters
- */
-
- public @OfflineRegion.DownloadState int getDownloadState() {
- return downloadState;
- }
-
- public long getCompletedResourceCount() {
- return completedResourceCount;
- }
-
- public long getCompletedResourceSize() {
- return completedResourceSize;
- }
-
- public long getCompletedTileCount() {
- return completedTileCount;
- }
-
- public long getCompletedTileSize() {
- return completedTileSize;
- }
-
- public long getRequiredResourceCount() {
- return requiredResourceCount;
- }
-
- public boolean isRequiredResourceCountPrecise() {
- return requiredResourceCountIsPrecise;
- }
+ @OfflineRegion.DownloadState
+ private int downloadState = OfflineRegion.STATE_INACTIVE;
+
+ /**
+ * The number of resources (inclusive of tiles) that have been fully downloaded
+ * and are ready for offline access.
+ */
+ private long completedResourceCount = 0;
+
+ /**
+ * The cumulative size, in bytes, of all resources (inclusive of tiles) that have
+ * been fully downloaded.
+ */
+ private long completedResourceSize = 0;
+
+ /**
+ * The number of tiles that have been fully downloaded and are ready for
+ * offline access.
+ */
+ private long completedTileCount = 0;
+
+ /**
+ * The cumulative size, in bytes, of all tiles that have been fully downloaded.
+ */
+ private long completedTileSize = 0;
+
+ /**
+ * The number of resources that are known to be required for this region. See the
+ * documentation for `requiredResourceCountIsPrecise` for an important caveat
+ * about this number.
+ */
+ private long requiredResourceCount = 0;
+
+ /**
+ * This property is true when the value of requiredResourceCount is a precise
+ * count of the number of required resources, and false when it is merely a lower
+ * bound.
+ * <p>
+ * Specifically, it is false during early phases of an offline download. Once
+ * style and tile sources have been downloaded, it is possible to calculate the
+ * precise number of required resources, at which point it is set to true.
+ */
+ private boolean requiredResourceCountIsPrecise = true;
+
+ /*
+ * Use setObserver(OfflineRegionObserver observer) to obtain a OfflineRegionStatus object.
+ */
+
+ private OfflineRegionStatus() {
+ // For JNI use only
+ }
+
+ /*
+ * Is the region complete?
+ */
+
+ public boolean isComplete() {
+ return (completedResourceCount == requiredResourceCount);
+ }
+
+ /*
+ * Getters
+ */
+
+ @OfflineRegion.DownloadState
+ public int getDownloadState() {
+ return downloadState;
+ }
+
+ public long getCompletedResourceCount() {
+ return completedResourceCount;
+ }
+
+ public long getCompletedResourceSize() {
+ return completedResourceSize;
+ }
+
+ public long getCompletedTileCount() {
+ return completedTileCount;
+ }
+
+ public long getCompletedTileSize() {
+ return completedTileSize;
+ }
+
+ public long getRequiredResourceCount() {
+ return requiredResourceCount;
+ }
+
+ public boolean isRequiredResourceCountPrecise() {
+ return requiredResourceCountIsPrecise;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition.java
index 5a0be6b33f..5fc844afe5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition.java
@@ -5,61 +5,61 @@ import com.mapbox.mapboxsdk.geometry.LatLngBounds;
/**
* An offline region defined by a style URL, geographic bounding box, zoom range, and
* device pixel ratio.
- *
+ * <p>
* Both minZoom and maxZoom must be ≥ 0, and maxZoom must be ≥ minZoom.
- *
+ * <p>
* maxZoom may be ∞, in which case for each tile source, the region will include
* tiles from minZoom up to the maximum zoom level provided by that source.
- *
+ * <p>
* pixelRatio must be ≥ 0 and should typically be 1.0 or 2.0.
*/
public class OfflineTilePyramidRegionDefinition implements OfflineRegionDefinition {
- private String styleURL;
- private LatLngBounds bounds;
- private double minZoom;
- private double maxZoom;
- private float pixelRatio;
+ private String styleURL;
+ private LatLngBounds bounds;
+ private double minZoom;
+ private double maxZoom;
+ private float pixelRatio;
- /*
- * Constructors
- */
+ /*
+ * Constructors
+ */
- private OfflineTilePyramidRegionDefinition() {
- // For JNI use only
- }
+ private OfflineTilePyramidRegionDefinition() {
+ // For JNI use only
+ }
- public OfflineTilePyramidRegionDefinition(
- String styleURL, LatLngBounds bounds, double minZoom, double maxZoom, float pixelRatio) {
- this.styleURL = styleURL;
- this.bounds = bounds;
- this.minZoom = minZoom;
- this.maxZoom = maxZoom;
- this.pixelRatio = pixelRatio;
- }
+ public OfflineTilePyramidRegionDefinition(
+ String styleURL, LatLngBounds bounds, double minZoom, double maxZoom, float pixelRatio) {
+ this.styleURL = styleURL;
+ this.bounds = bounds;
+ this.minZoom = minZoom;
+ this.maxZoom = maxZoom;
+ this.pixelRatio = pixelRatio;
+ }
- /*
- * Getters
- */
+ /*
+ * Getters
+ */
- public String getStyleURL() {
- return styleURL;
- }
+ public String getStyleURL() {
+ return styleURL;
+ }
- public LatLngBounds getBounds() {
- return bounds;
- }
+ public LatLngBounds getBounds() {
+ return bounds;
+ }
- public double getMinZoom() {
- return minZoom;
- }
+ public double getMinZoom() {
+ return minZoom;
+ }
- public double getMaxZoom() {
- return maxZoom;
- }
+ public double getMaxZoom() {
+ return maxZoom;
+ }
- public float getPixelRatio() {
- return pixelRatio;
- }
+ public float getPixelRatio() {
+ return pixelRatio;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java
index 893ffbc1ec..45523b41ab 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java
@@ -1,111 +1,108 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
-
-import com.mapbox.mapboxsdk.exceptions.ConversionException;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.UiThread;
-import static com.mapbox.mapboxsdk.utils.ColorUtils.*;
+import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
/**
* The background color or pattern of the map.
*
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#layers-background">The online documentation</a>
*/
+@UiThread
public class BackgroundLayer extends Layer {
- /**
- * Creates a BackgroundLayer.
- *
- * @param nativePtr pointer used by core
- */
- public BackgroundLayer(long nativePtr) {
- super(nativePtr);
+ /**
+ * Creates a BackgroundLayer.
+ *
+ * @param nativePtr pointer used by core
+ */
+ public BackgroundLayer(long nativePtr) {
+ super(nativePtr);
+ }
+
+ /**
+ * Creates a BackgroundLayer.
+ *
+ * @param layerId the id of the layer
+ */
+ public BackgroundLayer(String layerId) {
+ initialize(layerId);
+ }
+
+ protected native void initialize(String layerId);
+
+ /**
+ * Set a property or properties.
+ *
+ * @param properties the var-args properties
+ * @return This
+ */
+ public BackgroundLayer withProperties(@NonNull Property<?>... properties) {
+ setProperties(properties);
+ return this;
+ }
+
+ // Property getters
+
+ /**
+ * Get the BackgroundColor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getBackgroundColor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetBackgroundColor());
+ }
+
+ /**
+ * The color with which the background will be drawn.
+ *
+ * @return int representation of a rgba string color
+ * @throws RuntimeException thrown if property isn't a value
+ */
+ @ColorInt
+ public int getBackgroundColorAsInt() {
+ PropertyValue<String> value = getBackgroundColor();
+ if (value.isValue()) {
+ return rgbaToColor(value.getValue());
+ } else {
+ throw new RuntimeException("background-color was set as a Function");
}
+ }
- /**
- * Creates a BackgroundLayer.
- *
- * @param layerId the id of the layer
- */
- public BackgroundLayer(String layerId) {
- initialize(layerId);
- }
- protected native void initialize(String layerId);
-
- /**
- * Set a property or properties.
- *
- * @param properties the var-args properties
- * @return This
- */
- public BackgroundLayer withProperties(@NonNull Property<?>... properties) {
- setProperties(properties);
- return this;
- }
+ /**
+ * Get the BackgroundPattern property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getBackgroundPattern() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetBackgroundPattern());
+ }
- // Property getters
-
- /**
- * Get the BackgroundColor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getBackgroundColor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetBackgroundColor());
- }
- /**
- * The color with which the background will be drawn.
- *
- * @return int representation of a rgba string color
- * @throws RuntimeException thrown if property isn't a value
- */
- @ColorInt
- public int getBackgroundColorAsInt() {
- checkValidity();
- PropertyValue<String> value = getBackgroundColor();
- if (value.isValue()) {
- return rgbaToColor(value.getValue());
- } else {
- throw new RuntimeException("background-color was set as a Function");
- }
- }
+ /**
+ * Get the BackgroundOpacity property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getBackgroundOpacity() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetBackgroundOpacity());
+ }
-
- /**
- * Get the BackgroundPattern property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getBackgroundPattern() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetBackgroundPattern());
- }
-
- /**
- * Get the BackgroundOpacity property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getBackgroundOpacity() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetBackgroundOpacity());
- }
-
- private native Object nativeGetBackgroundColor();
+ private native Object nativeGetBackgroundColor();
- private native Object nativeGetBackgroundPattern();
+ private native Object nativeGetBackgroundPattern();
- private native Object nativeGetBackgroundOpacity();
+ private native Object nativeGetBackgroundOpacity();
- @Override
- protected native void finalize() throws Throwable;
+ @Override
+ protected native void finalize() throws Throwable;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CannotAddLayerException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CannotAddLayerException.java
new file mode 100644
index 0000000000..212493032d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CannotAddLayerException.java
@@ -0,0 +1,12 @@
+package com.mapbox.mapboxsdk.style.layers;
+
+/**
+ * Thrown when adding a layer to a map twice
+ */
+public class CannotAddLayerException extends RuntimeException {
+
+ public CannotAddLayerException(String message) {
+ super(message);
+ }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java
index a9f081b2fa..f16ab688d6 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java
@@ -1,227 +1,271 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
-
-import com.mapbox.mapboxsdk.exceptions.ConversionException;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.UiThread;
-import static com.mapbox.mapboxsdk.utils.ColorUtils.*;
+import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
/**
* A filled circle.
*
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#layers-circle">The online documentation</a>
*/
+@UiThread
public class CircleLayer extends Layer {
- /**
- * Creates a CircleLayer.
- *
- * @param nativePtr pointer used by core
- */
- public CircleLayer(long nativePtr) {
- super(nativePtr);
- }
+ /**
+ * Creates a CircleLayer.
+ *
+ * @param nativePtr pointer used by core
+ */
+ public CircleLayer(long nativePtr) {
+ super(nativePtr);
+ }
- /**
- * Creates a CircleLayer.
- *
- * @param layerId the id of the layer
- * @param sourceId the id of the source
- */
- public CircleLayer(String layerId, String sourceId) {
- initialize(layerId, sourceId);
- }
+ /**
+ * Creates a CircleLayer.
+ *
+ * @param layerId the id of the layer
+ * @param sourceId the id of the source
+ */
+ public CircleLayer(String layerId, String sourceId) {
+ initialize(layerId, sourceId);
+ }
- protected native void initialize(String layerId, String sourceId);
+ protected native void initialize(String layerId, String sourceId);
- /**
- * Set the source layer.
- *
- * @param sourceLayer the source layer to set
- */
- public void setSourceLayer(String sourceLayer) {
- checkValidity();
- nativeSetSourceLayer(sourceLayer);
- }
+ /**
+ * Set the source layer.
+ *
+ * @param sourceLayer the source layer to set
+ */
+ public void setSourceLayer(String sourceLayer) {
+ nativeSetSourceLayer(sourceLayer);
+ }
- /**
- * Set the source Layer.
- *
- * @param sourceLayer the source layer to set
- * @return This
- */
- public CircleLayer withSourceLayer(String sourceLayer) {
- setSourceLayer(sourceLayer);
- return this;
- }
- /**
- * Set a single filter.
- *
- * @param filter the filter to set
- */
- public void setFilter(Filter.Statement filter) {
- checkValidity();
- this.setFilter(filter.toArray());
- }
+ /**
+ * Set the source Layer.
+ *
+ * @param sourceLayer the source layer to set
+ * @return This
+ */
+ public CircleLayer withSourceLayer(String sourceLayer) {
+ setSourceLayer(sourceLayer);
+ return this;
+ }
- /**
- * Set an array of filters.
- *
- * @param filter the filter array to set
- */
- public void setFilter(Object[] filter) {
- checkValidity();
- nativeSetFilter(filter);
- }
+ /**
+ * Set a single filter.
+ *
+ * @param filter the filter to set
+ */
+ public void setFilter(Filter.Statement filter) {
+ this.setFilter(filter.toArray());
+ }
- /**
- * Set an array of filters.
- *
- * @param filter tthe filter array to set
- * @return This
- */
- public CircleLayer withFilter(Object[] filter) {
- setFilter(filter);
- return this;
- }
+ /**
+ * Set an array of filters.
+ *
+ * @param filter the filter array to set
+ */
+ public void setFilter(Object[] filter) {
+ nativeSetFilter(filter);
+ }
- /**
- * Set a single filter.
- *
- * @param filter the filter to set
- * @return This
- */
- public CircleLayer withFilter(Filter.Statement filter) {
- setFilter(filter);
- return this;
- }
+ /**
+ * Set an array of filters.
+ *
+ * @param filter tthe filter array to set
+ * @return This
+ */
+ public CircleLayer withFilter(Object[] filter) {
+ setFilter(filter);
+ return this;
+ }
+ /**
+ * Set a single filter.
+ *
+ * @param filter the filter to set
+ * @return This
+ */
+ public CircleLayer withFilter(Filter.Statement filter) {
+ setFilter(filter);
+ return this;
+ }
- /**
- * Set a property or properties.
- *
- * @param properties the var-args properties
- * @return This
- */
- public CircleLayer withProperties(@NonNull Property<?>... properties) {
- setProperties(properties);
- return this;
- }
- // Property getters
-
- /**
- * Get the CircleRadius property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getCircleRadius() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetCircleRadius());
- }
-
- /**
- * Get the CircleColor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getCircleColor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetCircleColor());
- }
- /**
- * The fill color of the circle.
- *
- * @return int representation of a rgba string color
- * @throws RuntimeException thrown if property isn't a value
- */
- @ColorInt
- public int getCircleColorAsInt() {
- checkValidity();
- PropertyValue<String> value = getCircleColor();
- if (value.isValue()) {
- return rgbaToColor(value.getValue());
- } else {
- throw new RuntimeException("circle-color was set as a Function");
- }
- }
+ /**
+ * Set a property or properties.
+ *
+ * @param properties the var-args properties
+ * @return This
+ */
+ public CircleLayer withProperties(@NonNull Property<?>... properties) {
+ setProperties(properties);
+ return this;
+ }
-
- /**
- * Get the CircleBlur property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getCircleBlur() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetCircleBlur());
- }
-
- /**
- * Get the CircleOpacity property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getCircleOpacity() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetCircleOpacity());
- }
-
- /**
- * Get the CircleTranslate property
- *
- * @return property wrapper value around Float[]
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float[]> getCircleTranslate() {
- checkValidity();
- return (PropertyValue<Float[]>) new PropertyValue(nativeGetCircleTranslate());
- }
-
- /**
- * Get the CircleTranslateAnchor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getCircleTranslateAnchor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetCircleTranslateAnchor());
+ // Property getters
+
+ /**
+ * Get the CircleRadius property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getCircleRadius() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetCircleRadius());
+ }
+
+ /**
+ * Get the CircleColor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getCircleColor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetCircleColor());
+ }
+
+ /**
+ * The fill color of the circle.
+ *
+ * @return int representation of a rgba string color
+ * @throws RuntimeException thrown if property isn't a value
+ */
+ @ColorInt
+ public int getCircleColorAsInt() {
+ PropertyValue<String> value = getCircleColor();
+ if (value.isValue()) {
+ return rgbaToColor(value.getValue());
+ } else {
+ throw new RuntimeException("circle-color was set as a Function");
}
-
- /**
- * Get the CirclePitchScale property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getCirclePitchScale() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetCirclePitchScale());
+ }
+
+
+ /**
+ * Get the CircleBlur property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getCircleBlur() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetCircleBlur());
+ }
+
+ /**
+ * Get the CircleOpacity property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getCircleOpacity() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetCircleOpacity());
+ }
+
+ /**
+ * Get the CircleTranslate property
+ *
+ * @return property wrapper value around Float[]
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float[]> getCircleTranslate() {
+ return (PropertyValue<Float[]>) new PropertyValue(nativeGetCircleTranslate());
+ }
+
+ /**
+ * Get the CircleTranslateAnchor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getCircleTranslateAnchor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetCircleTranslateAnchor());
+ }
+
+ /**
+ * Get the CirclePitchScale property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getCirclePitchScale() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetCirclePitchScale());
+ }
+
+ /**
+ * Get the CircleStrokeWidth property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getCircleStrokeWidth() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetCircleStrokeWidth());
+ }
+
+ /**
+ * Get the CircleStrokeColor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getCircleStrokeColor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetCircleStrokeColor());
+ }
+
+ /**
+ * The stroke color of the circle.
+ *
+ * @return int representation of a rgba string color
+ * @throws RuntimeException thrown if property isn't a value
+ */
+ @ColorInt
+ public int getCircleStrokeColorAsInt() {
+ PropertyValue<String> value = getCircleStrokeColor();
+ if (value.isValue()) {
+ return rgbaToColor(value.getValue());
+ } else {
+ throw new RuntimeException("circle-stroke-color was set as a Function");
}
-
- private native Object nativeGetCircleRadius();
+ }
+
+
+ /**
+ * Get the CircleStrokeOpacity property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getCircleStrokeOpacity() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetCircleStrokeOpacity());
+ }
+
+ private native Object nativeGetCircleRadius();
+
+ private native Object nativeGetCircleColor();
+
+ private native Object nativeGetCircleBlur();
+
+ private native Object nativeGetCircleOpacity();
- private native Object nativeGetCircleColor();
+ private native Object nativeGetCircleTranslate();
- private native Object nativeGetCircleBlur();
+ private native Object nativeGetCircleTranslateAnchor();
- private native Object nativeGetCircleOpacity();
+ private native Object nativeGetCirclePitchScale();
- private native Object nativeGetCircleTranslate();
+ private native Object nativeGetCircleStrokeWidth();
- private native Object nativeGetCircleTranslateAnchor();
+ private native Object nativeGetCircleStrokeColor();
- private native Object nativeGetCirclePitchScale();
+ private native Object nativeGetCircleStrokeOpacity();
- @Override
- protected native void finalize() throws Throwable;
+ @Override
+ protected native void finalize() throws Throwable;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java
index 4d578b54f8..7807556b78 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java
@@ -8,27 +8,28 @@ package com.mapbox.mapboxsdk.style.layers;
*/
public class CustomLayer extends Layer {
- public CustomLayer(String id,
- long context,
- long initializeFunction,
- long renderFunction,
- long deinitializeFunction) {
- initialize(id, initializeFunction, renderFunction, deinitializeFunction, context);
- }
+ public CustomLayer(String id,
+ long context,
+ long initializeFunction,
+ long renderFunction,
+ long deinitializeFunction) {
+ initialize(id, initializeFunction, renderFunction, deinitializeFunction, context);
+ }
- public CustomLayer(long nativePtr) {
- super(nativePtr);
- }
+ public CustomLayer(long nativePtr) {
+ super(nativePtr);
+ }
- public void update() {
- nativeUpdate();
- }
+ public void update() {
+ nativeUpdate();
+ }
- protected native void initialize(String id, long initializeFunction, long renderFunction, long deinitializeFunction, long context);
+ protected native void initialize(String id, long initializeFunction, long renderFunction, long deinitializeFunction,
+ long context);
- protected native void nativeUpdate();
+ protected native void nativeUpdate();
- @Override
- protected native void finalize() throws Throwable;
+ @Override
+ protected native void finalize() throws Throwable;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java
index e19dc20283..3f79c9306a 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java
@@ -1,244 +1,236 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
-
-import com.mapbox.mapboxsdk.exceptions.ConversionException;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.UiThread;
-import static com.mapbox.mapboxsdk.utils.ColorUtils.*;
+import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
/**
* A filled polygon with an optional stroked border.
*
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#layers-fill">The online documentation</a>
*/
+@UiThread
public class FillLayer extends Layer {
- /**
- * Creates a FillLayer.
- *
- * @param nativePtr pointer used by core
- */
- public FillLayer(long nativePtr) {
- super(nativePtr);
- }
-
- /**
- * Creates a FillLayer.
- *
- * @param layerId the id of the layer
- * @param sourceId the id of the source
- */
- public FillLayer(String layerId, String sourceId) {
- initialize(layerId, sourceId);
- }
-
- protected native void initialize(String layerId, String sourceId);
-
- /**
- * Set the source layer.
- *
- * @param sourceLayer the source layer to set
- */
- public void setSourceLayer(String sourceLayer) {
- checkValidity();
- nativeSetSourceLayer(sourceLayer);
- }
-
- /**
- * Set the source Layer.
- *
- * @param sourceLayer the source layer to set
- * @return This
- */
- public FillLayer withSourceLayer(String sourceLayer) {
- setSourceLayer(sourceLayer);
- return this;
- }
- /**
- * Set a single filter.
- *
- * @param filter the filter to set
- */
- public void setFilter(Filter.Statement filter) {
- checkValidity();
- this.setFilter(filter.toArray());
- }
-
- /**
- * Set an array of filters.
- *
- * @param filter the filter array to set
- */
- public void setFilter(Object[] filter) {
- checkValidity();
- nativeSetFilter(filter);
- }
-
- /**
- * Set an array of filters.
- *
- * @param filter tthe filter array to set
- * @return This
- */
- public FillLayer withFilter(Object[] filter) {
- setFilter(filter);
- return this;
- }
-
- /**
- * Set a single filter.
- *
- * @param filter the filter to set
- * @return This
- */
- public FillLayer withFilter(Filter.Statement filter) {
- setFilter(filter);
- return this;
- }
-
-
- /**
- * Set a property or properties.
- *
- * @param properties the var-args properties
- * @return This
- */
- public FillLayer withProperties(@NonNull Property<?>... properties) {
- setProperties(properties);
- return this;
- }
-
- // Property getters
-
- /**
- * Get the FillAntialias property
- *
- * @return property wrapper value around Boolean
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Boolean> getFillAntialias() {
- checkValidity();
- return (PropertyValue<Boolean>) new PropertyValue(nativeGetFillAntialias());
- }
-
- /**
- * Get the FillOpacity property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getFillOpacity() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetFillOpacity());
- }
-
- /**
- * Get the FillColor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getFillColor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetFillColor());
- }
- /**
- * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the color's opacity will not affect the opacity of the 1px stroke, if it is used.
- *
- * @return int representation of a rgba string color
- * @throws RuntimeException thrown if property isn't a value
- */
- @ColorInt
- public int getFillColorAsInt() {
- checkValidity();
- PropertyValue<String> value = getFillColor();
- if (value.isValue()) {
- return rgbaToColor(value.getValue());
- } else {
- throw new RuntimeException("fill-color was set as a Function");
- }
- }
-
-
- /**
- * Get the FillOutlineColor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getFillOutlineColor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetFillOutlineColor());
- }
- /**
- * The outline color of the fill. Matches the value of `fill-color` if unspecified.
- *
- * @return int representation of a rgba string color
- * @throws RuntimeException thrown if property isn't a value
- */
- @ColorInt
- public int getFillOutlineColorAsInt() {
- checkValidity();
- PropertyValue<String> value = getFillOutlineColor();
- if (value.isValue()) {
- return rgbaToColor(value.getValue());
- } else {
- throw new RuntimeException("fill-outline-color was set as a Function");
- }
- }
-
-
- /**
- * Get the FillTranslate property
- *
- * @return property wrapper value around Float[]
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float[]> getFillTranslate() {
- checkValidity();
- return (PropertyValue<Float[]>) new PropertyValue(nativeGetFillTranslate());
- }
-
- /**
- * Get the FillTranslateAnchor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getFillTranslateAnchor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetFillTranslateAnchor());
- }
-
- /**
- * Get the FillPattern property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getFillPattern() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetFillPattern());
- }
-
- private native Object nativeGetFillAntialias();
-
- private native Object nativeGetFillOpacity();
-
- private native Object nativeGetFillColor();
-
- private native Object nativeGetFillOutlineColor();
-
- private native Object nativeGetFillTranslate();
-
- private native Object nativeGetFillTranslateAnchor();
-
- private native Object nativeGetFillPattern();
-
-
- @Override
- protected native void finalize() throws Throwable;
+ /**
+ * Creates a FillLayer.
+ *
+ * @param nativePtr pointer used by core
+ */
+ public FillLayer(long nativePtr) {
+ super(nativePtr);
+ }
+
+ /**
+ * Creates a FillLayer.
+ *
+ * @param layerId the id of the layer
+ * @param sourceId the id of the source
+ */
+ public FillLayer(String layerId, String sourceId) {
+ initialize(layerId, sourceId);
+ }
+
+ protected native void initialize(String layerId, String sourceId);
+
+ /**
+ * Set the source layer.
+ *
+ * @param sourceLayer the source layer to set
+ */
+ public void setSourceLayer(String sourceLayer) {
+ nativeSetSourceLayer(sourceLayer);
+ }
+
+ /**
+ * Set the source Layer.
+ *
+ * @param sourceLayer the source layer to set
+ * @return This
+ */
+ public FillLayer withSourceLayer(String sourceLayer) {
+ setSourceLayer(sourceLayer);
+ return this;
+ }
+
+ /**
+ * Set a single filter.
+ *
+ * @param filter the filter to set
+ */
+ public void setFilter(Filter.Statement filter) {
+ this.setFilter(filter.toArray());
+ }
+
+ /**
+ * Set an array of filters.
+ *
+ * @param filter the filter array to set
+ */
+ public void setFilter(Object[] filter) {
+ nativeSetFilter(filter);
+ }
+
+ /**
+ * Set an array of filters.
+ *
+ * @param filter tthe filter array to set
+ * @return This
+ */
+ public FillLayer withFilter(Object[] filter) {
+ setFilter(filter);
+ return this;
+ }
+
+ /**
+ * Set a single filter.
+ *
+ * @param filter the filter to set
+ * @return This
+ */
+ public FillLayer withFilter(Filter.Statement filter) {
+ setFilter(filter);
+ return this;
+ }
+
+
+ /**
+ * Set a property or properties.
+ *
+ * @param properties the var-args properties
+ * @return This
+ */
+ public FillLayer withProperties(@NonNull Property<?>... properties) {
+ setProperties(properties);
+ return this;
+ }
+
+ // Property getters
+
+ /**
+ * Get the FillAntialias property
+ *
+ * @return property wrapper value around Boolean
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Boolean> getFillAntialias() {
+ return (PropertyValue<Boolean>) new PropertyValue(nativeGetFillAntialias());
+ }
+
+ /**
+ * Get the FillOpacity property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getFillOpacity() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetFillOpacity());
+ }
+
+ /**
+ * Get the FillColor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getFillColor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetFillColor());
+ }
+
+ /**
+ * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the
+ * color's opacity will not affect the opacity of the 1px stroke, if it is used.
+ *
+ * @return int representation of a rgba string color
+ * @throws RuntimeException thrown if property isn't a value
+ */
+ @ColorInt
+ public int getFillColorAsInt() {
+ PropertyValue<String> value = getFillColor();
+ if (value.isValue()) {
+ return rgbaToColor(value.getValue());
+ } else {
+ throw new RuntimeException("fill-color was set as a Function");
+ }
+ }
+
+
+ /**
+ * Get the FillOutlineColor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getFillOutlineColor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetFillOutlineColor());
+ }
+
+ /**
+ * The outline color of the fill. Matches the value of `fill-color` if unspecified.
+ *
+ * @return int representation of a rgba string color
+ * @throws RuntimeException thrown if property isn't a value
+ */
+ @ColorInt
+ public int getFillOutlineColorAsInt() {
+ PropertyValue<String> value = getFillOutlineColor();
+ if (value.isValue()) {
+ return rgbaToColor(value.getValue());
+ } else {
+ throw new RuntimeException("fill-outline-color was set as a Function");
+ }
+ }
+
+
+ /**
+ * Get the FillTranslate property
+ *
+ * @return property wrapper value around Float[]
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float[]> getFillTranslate() {
+ return (PropertyValue<Float[]>) new PropertyValue(nativeGetFillTranslate());
+ }
+
+ /**
+ * Get the FillTranslateAnchor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getFillTranslateAnchor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetFillTranslateAnchor());
+ }
+
+ /**
+ * Get the FillPattern property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getFillPattern() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetFillPattern());
+ }
+
+ private native Object nativeGetFillAntialias();
+
+ private native Object nativeGetFillOpacity();
+
+ private native Object nativeGetFillColor();
+
+ private native Object nativeGetFillOutlineColor();
+
+ private native Object nativeGetFillTranslate();
+
+ private native Object nativeGetFillTranslateAnchor();
+
+ private native Object nativeGetFillPattern();
+
+
+ @Override
+ protected native void finalize() throws Throwable;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java
index 6f881e4960..643a126388 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java
@@ -10,221 +10,221 @@ import java.util.Collections;
*/
public class Filter {
- /**
- * Base {@link Filter} statement. Subclassed to provide concrete statements.
- */
- public abstract static class Statement {
- protected final String operator;
-
- public Statement(String operator) {
- this.operator = operator;
- }
-
- /**
- * Generate a raw array representation of the filter
- *
- * @return the filter represented as an array
- */
- public abstract Object[] toArray();
- }
-
- /**
- * Represents a {@link Filter} statement. Can be unary (eg `has()`, etc) or take any number of values.
- */
- private static class SimpleStatement extends Statement {
- private final String key;
- private final Object[] values;
-
- /**
- * @param operator the operator (eg `=`, etc)
- * @param key the property key
- * @param values the values to operate on, if any
- */
- SimpleStatement(String operator, String key, Object... values) {
- super(operator);
- this.key = key;
- this.values = values;
- }
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Object[] toArray() {
- ArrayList<Object> array = new ArrayList<>(2 + values.length);
- array.add(operator);
- array.add(key);
- Collections.addAll(array, values);
- return array.toArray();
- }
- }
-
- /**
- * Represents a collection of {@link Statement}s with an operator that describes their relationship
- */
- private static class CompoundStatement extends Statement {
- private final Statement[] statements;
-
- /**
- * @param operator the relationship operator
- * @param statements the statements to compound
- */
- CompoundStatement(String operator, Statement... statements) {
- super(operator);
- this.statements = statements;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Object[] toArray() {
- ArrayList<Object> array = new ArrayList<>(1 + statements.length);
- array.add(operator);
- for (Statement statement : statements) {
- array.add(statement.toArray());
- }
- return array.toArray();
- }
- }
-
- /**
- * Groups a collection of statements in an 'all' relationship
- *
- * @param statements the collection of statements
- * @return the statements compounded
- */
- public static Statement all(Statement... statements) {
- return new CompoundStatement("all", statements);
- }
-
- /**
- * Groups a collection of statements in an 'any' relationship
- *
- * @param statements the collection of statements
- * @return the statements compounded
- */
- public static Statement any(Statement... statements) {
- return new CompoundStatement("any", statements);
- }
-
- /**
- * Groups a collection of statements in an 'none' relationship
- *
- * @param statements the collection of statements
- * @return the statements compounded
- */
- public static Statement none(Statement... statements) {
- return new CompoundStatement("none", statements);
- }
-
- /**
- * Check the property's existence
- *
- * @param key the property key
- * @return the statement
- */
- public static Statement has(String key) {
- return new SimpleStatement("has", key);
- }
+ /**
+ * Base {@link Filter} statement. Subclassed to provide concrete statements.
+ */
+ public abstract static class Statement {
+ protected final String operator;
- /**
- * Check the property's existence, negated
- *
- * @param key the property key
- * @return the statement
- */
- public static Statement notHas(String key) {
- return new SimpleStatement("!has", key);
+ public Statement(String operator) {
+ this.operator = operator;
}
/**
- * Check the property equals the given value
+ * Generate a raw array representation of the filter
*
- * @param key the property key
- * @param value the value to check against
- * @return the statement
- */
- public static Statement eq(String key, Object value) {
- return new SimpleStatement("==", key, value);
- }
-
- /**
- * Check the property does not equals the given value
- *
- * @param key the property key
- * @param value the value to check against
- * @return the statement
- */
- public static Statement neq(String key, Object value) {
- return new SimpleStatement("!=", key, value);
- }
-
- /**
- * Check the property exceeds the given value
- *
- * @param key the property key
- * @param value the value to check against
- * @return the statement
- */
- public static Statement gt(String key, Object value) {
- return new SimpleStatement(">", key, value);
- }
-
- /**
- * Check the property exceeds or equals the given value
- *
- * @param key the property key
- * @param value the value to check against
- * @return the statement
- */
- public static Statement gte(String key, Object value) {
- return new SimpleStatement(">=", key, value);
- }
-
- /**
- * Check the property does not exceeds the given value
- *
- * @param key the property key
- * @param value the value to check against
- * @return the statement
- */
- public static Statement lt(String key, Object value) {
- return new SimpleStatement("<", key, value);
- }
-
- /**
- * Check the property equals or does not exceeds the given value
- *
- * @param key the property key
- * @param value the value to check against
- * @return the statement
- */
- public static Statement lte(String key, Object value) {
- return new SimpleStatement("<=", key, value);
- }
-
- /**
- * Check the property is within the given set
- *
- * @param key the property key
- * @param values the set of values to check against
- * @return the statement
- */
- public static Statement in(String key, Object... values) {
- return new SimpleStatement("in", key, values);
- }
-
- /**
- * Check the property is not within the given set
- *
- * @param key the property key
- * @param values the set of values to check against
- * @return the statement
- */
- public static Statement notIn(String key, Object... values) {
- return new SimpleStatement("!in", key, values);
- }
+ * @return the filter represented as an array
+ */
+ public abstract Object[] toArray();
+ }
+
+ /**
+ * Represents a {@link Filter} statement. Can be unary (eg `has()`, etc) or take any number of values.
+ */
+ private static class SimpleStatement extends Statement {
+ private final String key;
+ private final Object[] values;
+
+ /**
+ * @param operator the operator (eg `=`, etc)
+ * @param key the property key
+ * @param values the values to operate on, if any
+ */
+ SimpleStatement(String operator, String key, Object... values) {
+ super(operator);
+ this.key = key;
+ this.values = values;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Object[] toArray() {
+ ArrayList<Object> array = new ArrayList<>(2 + values.length);
+ array.add(operator);
+ array.add(key);
+ Collections.addAll(array, values);
+ return array.toArray();
+ }
+ }
+
+ /**
+ * Represents a collection of {@link Statement}s with an operator that describes their relationship
+ */
+ private static class CompoundStatement extends Statement {
+ private final Statement[] statements;
+
+ /**
+ * @param operator the relationship operator
+ * @param statements the statements to compound
+ */
+ CompoundStatement(String operator, Statement... statements) {
+ super(operator);
+ this.statements = statements;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Object[] toArray() {
+ ArrayList<Object> array = new ArrayList<>(1 + statements.length);
+ array.add(operator);
+ for (Statement statement : statements) {
+ array.add(statement.toArray());
+ }
+ return array.toArray();
+ }
+ }
+
+ /**
+ * Groups a collection of statements in an 'all' relationship
+ *
+ * @param statements the collection of statements
+ * @return the statements compounded
+ */
+ public static Statement all(Statement... statements) {
+ return new CompoundStatement("all", statements);
+ }
+
+ /**
+ * Groups a collection of statements in an 'any' relationship
+ *
+ * @param statements the collection of statements
+ * @return the statements compounded
+ */
+ public static Statement any(Statement... statements) {
+ return new CompoundStatement("any", statements);
+ }
+
+ /**
+ * Groups a collection of statements in an 'none' relationship
+ *
+ * @param statements the collection of statements
+ * @return the statements compounded
+ */
+ public static Statement none(Statement... statements) {
+ return new CompoundStatement("none", statements);
+ }
+
+ /**
+ * Check the property's existence
+ *
+ * @param key the property key
+ * @return the statement
+ */
+ public static Statement has(String key) {
+ return new SimpleStatement("has", key);
+ }
+
+ /**
+ * Check the property's existence, negated
+ *
+ * @param key the property key
+ * @return the statement
+ */
+ public static Statement notHas(String key) {
+ return new SimpleStatement("!has", key);
+ }
+
+ /**
+ * Check the property equals the given value
+ *
+ * @param key the property key
+ * @param value the value to check against
+ * @return the statement
+ */
+ public static Statement eq(String key, Object value) {
+ return new SimpleStatement("==", key, value);
+ }
+
+ /**
+ * Check the property does not equals the given value
+ *
+ * @param key the property key
+ * @param value the value to check against
+ * @return the statement
+ */
+ public static Statement neq(String key, Object value) {
+ return new SimpleStatement("!=", key, value);
+ }
+
+ /**
+ * Check the property exceeds the given value
+ *
+ * @param key the property key
+ * @param value the value to check against
+ * @return the statement
+ */
+ public static Statement gt(String key, Object value) {
+ return new SimpleStatement(">", key, value);
+ }
+
+ /**
+ * Check the property exceeds or equals the given value
+ *
+ * @param key the property key
+ * @param value the value to check against
+ * @return the statement
+ */
+ public static Statement gte(String key, Object value) {
+ return new SimpleStatement(">=", key, value);
+ }
+
+ /**
+ * Check the property does not exceeds the given value
+ *
+ * @param key the property key
+ * @param value the value to check against
+ * @return the statement
+ */
+ public static Statement lt(String key, Object value) {
+ return new SimpleStatement("<", key, value);
+ }
+
+ /**
+ * Check the property equals or does not exceeds the given value
+ *
+ * @param key the property key
+ * @param value the value to check against
+ * @return the statement
+ */
+ public static Statement lte(String key, Object value) {
+ return new SimpleStatement("<=", key, value);
+ }
+
+ /**
+ * Check the property is within the given set
+ *
+ * @param key the property key
+ * @param values the set of values to check against
+ * @return the statement
+ */
+ public static Statement in(String key, Object... values) {
+ return new SimpleStatement("in", key, values);
+ }
+
+ /**
+ * Check the property is not within the given set
+ *
+ * @param key the property key
+ * @param values the set of values to check against
+ * @return the statement
+ */
+ public static Statement notIn(String key, Object... values) {
+ return new SimpleStatement("!in", key, values);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Function.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Function.java
index e147b5204f..900fe10476 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Function.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Function.java
@@ -19,119 +19,119 @@ import java.util.Map;
*/
public class Function<T> {
- /**
- * A stop represents a certain point in the range of this function
- *
- * @param <I> input
- * @param <O> output
- */
- public static class Stop<I, O> {
- public final I in;
- public final O out;
-
- Stop(I in, O out) {
- this.in = in;
- this.out = out;
- }
-
- /**
- * @return an array representation of the Stop
- */
- Object[] toValueObject() {
- return new Object[]{in, out};
- }
-
- @Override
- public String toString() {
- return String.format("[%s, %s]", in, out);
- }
- }
-
- /**
- * Zoom functions allow the appearance of a map feature to change with map’s zoom.
- * Zoom functions can be used to create the illusion of depth and control data density.
- * Each stop is an array with two elements, the first is a zoom and the second is a function output value.
- *
- * @param stops the stops that define the function
- * @param <T> the property type
- * @return the {@link Function}
- */
- @SafeVarargs
- public static <T> Function<T> zoom(@NonNull @Size(min = 1) Stop<Float, T>... stops) {
- return new Function<T>(stops);
+ /**
+ * A stop represents a certain point in the range of this function
+ *
+ * @param <I> input
+ * @param <O> output
+ */
+ public static class Stop<I, O> {
+ public final I in;
+ public final O out;
+
+ Stop(I in, O out) {
+ this.in = in;
+ this.out = out;
}
-
/**
- * Zoom functions allow the appearance of a map feature to change with map’s zoom.
- * Zoom functions can be used to create the illusion of depth and control data density.
- * Each stop is an array with two elements, the first is a zoom and the second is a function output value.
- *
- * @param stops the stops that define the function
- * @param base the exponential base of the interpolation curve - Default 1
- * @param <T> the property type
- * @return the {@link Function}
+ * @return an array representation of the Stop
*/
- @SafeVarargs
- public static <T> Function<T> zoom(
- @FloatRange(from = 0, to = 1, fromInclusive = false, toInclusive = false) float base,
- @NonNull @Size(min = 1) Stop<Float, T>... stops) {
- return new Function<T>(stops)
- .withBase(base);
+ Object[] toValueObject() {
+ return new Object[] {in, out};
}
- /**
- * Creates a stop to use in a {@link Function}
- *
- * @param in the input for the stop
- * @param output the output for the stop
- * @param <T> the output property type
- * @return the {@link Stop}
- */
- public static <T> Stop<Float, T> stop(float in, Property<T> output) {
- return new Stop<>(in, output.value);
+ @Override
+ public String toString() {
+ return String.format("[%s, %s]", in, out);
}
-
- private final Stop<Float, T>[] stops;
- private Float base;
-
- Function(@NonNull @Size(min = 1) Stop<Float, T>[] stops) {
- this.stops = stops;
+ }
+
+ /**
+ * Zoom functions allow the appearance of a map feature to change with map’s zoom.
+ * Zoom functions can be used to create the illusion of depth and control data density.
+ * Each stop is an array with two elements, the first is a zoom and the second is a function output value.
+ *
+ * @param stops the stops that define the function
+ * @param <T> the property type
+ * @return the {@link Function}
+ */
+ @SafeVarargs
+ public static <T> Function<T> zoom(@NonNull @Size(min = 1) Stop<Float, T>... stops) {
+ return new Function<T>(stops);
+ }
+
+
+ /**
+ * Zoom functions allow the appearance of a map feature to change with map’s zoom.
+ * Zoom functions can be used to create the illusion of depth and control data density.
+ * Each stop is an array with two elements, the first is a zoom and the second is a function output value.
+ *
+ * @param stops the stops that define the function
+ * @param base the exponential base of the interpolation curve - Default 1
+ * @param <T> the property type
+ * @return the {@link Function}
+ */
+ @SafeVarargs
+ public static <T> Function<T> zoom(
+ @FloatRange(from = 0, to = 1, fromInclusive = false, toInclusive = false) float base,
+ @NonNull @Size(min = 1) Stop<Float, T>... stops) {
+ return new Function<T>(stops)
+ .withBase(base);
+ }
+
+ /**
+ * Creates a stop to use in a {@link Function}
+ *
+ * @param in the input for the stop
+ * @param output the output for the stop
+ * @param <T> the output property type
+ * @return the {@link Stop}
+ */
+ public static <T> Stop<Float, T> stop(float in, Property<T> output) {
+ return new Stop<>(in, output.value);
+ }
+
+ private final Stop<Float, T>[] stops;
+ private Float base;
+
+ Function(@NonNull @Size(min = 1) Stop<Float, T>[] stops) {
+ this.stops = stops;
+ }
+
+ Function<T> withBase(float base) {
+ this.base = base;
+ return this;
+ }
+
+ /**
+ * @return the base
+ */
+ @Nullable
+ public Float getBase() {
+ return base;
+ }
+
+ /**
+ * @return the stops in this function
+ */
+ public Stop<Float, T>[] getStops() {
+ return stops;
+ }
+
+ Map<String, Object> toValueObject() {
+ Object[] stopsValue = new Object[stops.length];
+
+ for (int i = 0; i < stopsValue.length; i++) {
+ Stop stop = stops[i];
+ stopsValue[i] = stop.toValueObject();
}
- Function<T> withBase(float base) {
- this.base = base;
- return this;
- }
-
- /**
- * @return the base
- */
- @Nullable
- public Float getBase() {
- return base;
- }
-
- /**
- * @return the stops in this function
- */
- public Stop<Float, T>[] getStops() {
- return stops;
- }
-
- Map<String, Object> toValueObject() {
- Object[] stopsValue = new Object[stops.length];
-
- for (int i = 0; i < stopsValue.length; i++) {
- Stop stop = stops[i];
- stopsValue[i] = stop.toValueObject();
- }
-
- Map<String, Object> value = new HashMap<>();
- if (base != null) {
- value.put("base", base);
- }
- value.put("stops", stopsValue);
- return value;
+ Map<String, Object> value = new HashMap<>();
+ if (base != null) {
+ value.put("base", base);
}
+ value.put("stops", stopsValue);
+ return value;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java
index 54d18962ce..2878d76430 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java
@@ -7,101 +7,83 @@ import android.support.annotation.NonNull;
*/
public abstract class Layer {
- private long nativePtr;
- private boolean invalidated;
+ private long nativePtr;
+ private boolean invalidated;
- public Layer(long nativePtr) {
- this.nativePtr = nativePtr;
- }
-
- public Layer() {
- }
+ public Layer(long nativePtr) {
+ this.nativePtr = nativePtr;
+ }
- public void setProperties(@NonNull Property<?>... properties) {
- checkValidity();
-
- if (properties.length == 0) {
- return;
- }
-
- for (Property<?> property : properties) {
- Object converted = convertValue(property.value);
- if (property instanceof PaintProperty) {
- nativeSetPaintProperty(property.name, converted);
- } else {
- nativeSetLayoutProperty(property.name, converted);
- }
- }
- }
+ public Layer() {
+ }
- public String getId() {
- checkValidity();
- return nativeGetId();
+ public void setProperties(@NonNull Property<?>... properties) {
+ if (properties.length == 0) {
+ return;
}
- public PropertyValue<String> getVisibility() {
- checkValidity();
- return new PropertyValue<>(nativeGetVisibility());
+ for (Property<?> property : properties) {
+ Object converted = convertValue(property.value);
+ if (property instanceof PaintProperty) {
+ nativeSetPaintProperty(property.name, converted);
+ } else {
+ nativeSetLayoutProperty(property.name, converted);
+ }
}
+ }
- public float getMinZoom() {
- checkValidity();
- return nativeGetMinZoom();
- }
+ public String getId() {
+ return nativeGetId();
+ }
- public float getMaxZoom() {
- checkValidity();
- return nativeGetMaxZoom();
- }
+ public PropertyValue<String> getVisibility() {
+ return new PropertyValue<>(nativeGetVisibility());
+ }
- public void setMinZoom(float zoom) {
- checkValidity();
- nativeSetMinZoom(zoom);
- }
+ public float getMinZoom() {
+ return nativeGetMinZoom();
+ }
- public void setMaxZoom(float zoom) {
- checkValidity();
- nativeSetMaxZoom(zoom);
- }
+ public float getMaxZoom() {
+ return nativeGetMaxZoom();
+ }
- @Override
- protected native void finalize() throws Throwable;
+ public void setMinZoom(float zoom) {
+ nativeSetMinZoom(zoom);
+ }
- protected native String nativeGetId();
+ public void setMaxZoom(float zoom) {
+ nativeSetMaxZoom(zoom);
+ }
- protected native Object nativeGetVisibility();
+ @Override
+ protected native void finalize() throws Throwable;
- protected native void nativeSetLayoutProperty(String name, Object value);
+ protected native String nativeGetId();
- protected native void nativeSetPaintProperty(String name, Object value);
+ protected native Object nativeGetVisibility();
- protected native void nativeSetFilter(Object[] filter);
+ protected native void nativeSetLayoutProperty(String name, Object value);
- protected native void nativeSetSourceLayer(String sourceLayer);
+ protected native void nativeSetPaintProperty(String name, Object value);
- protected native float nativeGetMinZoom();
+ protected native void nativeSetFilter(Object[] filter);
- protected native float nativeGetMaxZoom();
+ protected native void nativeSetSourceLayer(String sourceLayer);
- protected native void nativeSetMinZoom(float zoom);
+ protected native float nativeGetMinZoom();
- protected native void nativeSetMaxZoom(float zoom);
+ protected native float nativeGetMaxZoom();
- public long getNativePtr() {
- return nativePtr;
- }
+ protected native void nativeSetMinZoom(float zoom);
- private Object convertValue(Object value) {
- return value != null && value instanceof Function ? ((Function) value).toValueObject() : value;
- }
+ protected native void nativeSetMaxZoom(float zoom);
- protected void checkValidity() {
- if (invalidated) {
- throw new RuntimeException("Layer has been invalidated. Request a new reference after adding");
- }
- }
+ public long getNativePtr() {
+ return nativePtr;
+ }
- public final void invalidate() {
- this.invalidated = true;
- }
+ private Object convertValue(Object value) {
+ return value != null && value instanceof Function ? ((Function) value).toValueObject() : value;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LayoutProperty.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LayoutProperty.java
index 553554270e..4c0b52be55 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LayoutProperty.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LayoutProperty.java
@@ -2,8 +2,8 @@ package com.mapbox.mapboxsdk.style.layers;
class LayoutProperty<T> extends Property<T> {
- LayoutProperty(String name, T value) {
- super(name, value);
- }
+ LayoutProperty(String name, T value) {
+ super(name, value);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java
index 896558a011..4c52a40b05 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java
@@ -1,318 +1,302 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
-
-import com.mapbox.mapboxsdk.exceptions.ConversionException;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.UiThread;
-import static com.mapbox.mapboxsdk.utils.ColorUtils.*;
+import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
/**
* A stroked line.
*
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#layers-line">The online documentation</a>
*/
+@UiThread
public class LineLayer extends Layer {
- /**
- * Creates a LineLayer.
- *
- * @param nativePtr pointer used by core
- */
- public LineLayer(long nativePtr) {
- super(nativePtr);
- }
-
- /**
- * Creates a LineLayer.
- *
- * @param layerId the id of the layer
- * @param sourceId the id of the source
- */
- public LineLayer(String layerId, String sourceId) {
- initialize(layerId, sourceId);
- }
-
- protected native void initialize(String layerId, String sourceId);
-
- /**
- * Set the source layer.
- *
- * @param sourceLayer the source layer to set
- */
- public void setSourceLayer(String sourceLayer) {
- checkValidity();
- nativeSetSourceLayer(sourceLayer);
- }
-
- /**
- * Set the source Layer.
- *
- * @param sourceLayer the source layer to set
- * @return This
- */
- public LineLayer withSourceLayer(String sourceLayer) {
- setSourceLayer(sourceLayer);
- return this;
- }
- /**
- * Set a single filter.
- *
- * @param filter the filter to set
- */
- public void setFilter(Filter.Statement filter) {
- checkValidity();
- this.setFilter(filter.toArray());
- }
-
- /**
- * Set an array of filters.
- *
- * @param filter the filter array to set
- */
- public void setFilter(Object[] filter) {
- checkValidity();
- nativeSetFilter(filter);
- }
-
- /**
- * Set an array of filters.
- *
- * @param filter tthe filter array to set
- * @return This
- */
- public LineLayer withFilter(Object[] filter) {
- setFilter(filter);
- return this;
- }
-
- /**
- * Set a single filter.
- *
- * @param filter the filter to set
- * @return This
- */
- public LineLayer withFilter(Filter.Statement filter) {
- setFilter(filter);
- return this;
- }
-
-
- /**
- * Set a property or properties.
- *
- * @param properties the var-args properties
- * @return This
- */
- public LineLayer withProperties(@NonNull Property<?>... properties) {
- setProperties(properties);
- return this;
- }
-
- // Property getters
-
- /**
- * Get the LineCap property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getLineCap() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetLineCap());
- }
-
- /**
- * Get the LineJoin property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getLineJoin() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetLineJoin());
- }
-
- /**
- * Get the LineMiterLimit property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getLineMiterLimit() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetLineMiterLimit());
- }
-
- /**
- * Get the LineRoundLimit property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getLineRoundLimit() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetLineRoundLimit());
- }
-
- /**
- * Get the LineOpacity property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getLineOpacity() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetLineOpacity());
- }
-
- /**
- * Get the LineColor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getLineColor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetLineColor());
- }
- /**
- * The color with which the line will be drawn.
- *
- * @return int representation of a rgba string color
- * @throws RuntimeException thrown if property isn't a value
- */
- @ColorInt
- public int getLineColorAsInt() {
- checkValidity();
- PropertyValue<String> value = getLineColor();
- if (value.isValue()) {
- return rgbaToColor(value.getValue());
- } else {
- throw new RuntimeException("line-color was set as a Function");
- }
- }
-
-
- /**
- * Get the LineTranslate property
- *
- * @return property wrapper value around Float[]
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float[]> getLineTranslate() {
- checkValidity();
- return (PropertyValue<Float[]>) new PropertyValue(nativeGetLineTranslate());
- }
-
- /**
- * Get the LineTranslateAnchor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getLineTranslateAnchor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetLineTranslateAnchor());
- }
-
- /**
- * Get the LineWidth property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getLineWidth() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetLineWidth());
- }
-
- /**
- * Get the LineGapWidth property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getLineGapWidth() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetLineGapWidth());
- }
-
- /**
- * Get the LineOffset property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getLineOffset() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetLineOffset());
+ /**
+ * Creates a LineLayer.
+ *
+ * @param nativePtr pointer used by core
+ */
+ public LineLayer(long nativePtr) {
+ super(nativePtr);
+ }
+
+ /**
+ * Creates a LineLayer.
+ *
+ * @param layerId the id of the layer
+ * @param sourceId the id of the source
+ */
+ public LineLayer(String layerId, String sourceId) {
+ initialize(layerId, sourceId);
+ }
+
+ protected native void initialize(String layerId, String sourceId);
+
+ /**
+ * Set the source layer.
+ *
+ * @param sourceLayer the source layer to set
+ */
+ public void setSourceLayer(String sourceLayer) {
+ nativeSetSourceLayer(sourceLayer);
+ }
+
+ /**
+ * Set the source Layer.
+ *
+ * @param sourceLayer the source layer to set
+ * @return This
+ */
+ public LineLayer withSourceLayer(String sourceLayer) {
+ setSourceLayer(sourceLayer);
+ return this;
+ }
+
+ /**
+ * Set a single filter.
+ *
+ * @param filter the filter to set
+ */
+ public void setFilter(Filter.Statement filter) {
+ this.setFilter(filter.toArray());
+ }
+
+ /**
+ * Set an array of filters.
+ *
+ * @param filter the filter array to set
+ */
+ public void setFilter(Object[] filter) {
+ nativeSetFilter(filter);
+ }
+
+ /**
+ * Set an array of filters.
+ *
+ * @param filter tthe filter array to set
+ * @return This
+ */
+ public LineLayer withFilter(Object[] filter) {
+ setFilter(filter);
+ return this;
+ }
+
+ /**
+ * Set a single filter.
+ *
+ * @param filter the filter to set
+ * @return This
+ */
+ public LineLayer withFilter(Filter.Statement filter) {
+ setFilter(filter);
+ return this;
+ }
+
+
+ /**
+ * Set a property or properties.
+ *
+ * @param properties the var-args properties
+ * @return This
+ */
+ public LineLayer withProperties(@NonNull Property<?>... properties) {
+ setProperties(properties);
+ return this;
+ }
+
+ // Property getters
+
+ /**
+ * Get the LineCap property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getLineCap() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetLineCap());
+ }
+
+ /**
+ * Get the LineJoin property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getLineJoin() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetLineJoin());
+ }
+
+ /**
+ * Get the LineMiterLimit property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getLineMiterLimit() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetLineMiterLimit());
+ }
+
+ /**
+ * Get the LineRoundLimit property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getLineRoundLimit() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetLineRoundLimit());
+ }
+
+ /**
+ * Get the LineOpacity property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getLineOpacity() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetLineOpacity());
+ }
+
+ /**
+ * Get the LineColor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getLineColor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetLineColor());
+ }
+
+ /**
+ * The color with which the line will be drawn.
+ *
+ * @return int representation of a rgba string color
+ * @throws RuntimeException thrown if property isn't a value
+ */
+ @ColorInt
+ public int getLineColorAsInt() {
+ PropertyValue<String> value = getLineColor();
+ if (value.isValue()) {
+ return rgbaToColor(value.getValue());
+ } else {
+ throw new RuntimeException("line-color was set as a Function");
}
-
- /**
- * Get the LineBlur property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getLineBlur() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetLineBlur());
- }
-
- /**
- * Get the LineDasharray property
- *
- * @return property wrapper value around Float[]
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float[]> getLineDasharray() {
- checkValidity();
- return (PropertyValue<Float[]>) new PropertyValue(nativeGetLineDasharray());
- }
-
- /**
- * Get the LinePattern property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getLinePattern() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetLinePattern());
- }
-
- private native Object nativeGetLineCap();
-
- private native Object nativeGetLineJoin();
-
- private native Object nativeGetLineMiterLimit();
-
- private native Object nativeGetLineRoundLimit();
-
- private native Object nativeGetLineOpacity();
-
- private native Object nativeGetLineColor();
-
- private native Object nativeGetLineTranslate();
-
- private native Object nativeGetLineTranslateAnchor();
-
- private native Object nativeGetLineWidth();
-
- private native Object nativeGetLineGapWidth();
-
- private native Object nativeGetLineOffset();
-
- private native Object nativeGetLineBlur();
-
- private native Object nativeGetLineDasharray();
-
- private native Object nativeGetLinePattern();
-
-
- @Override
- protected native void finalize() throws Throwable;
+ }
+
+
+ /**
+ * Get the LineTranslate property
+ *
+ * @return property wrapper value around Float[]
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float[]> getLineTranslate() {
+ return (PropertyValue<Float[]>) new PropertyValue(nativeGetLineTranslate());
+ }
+
+ /**
+ * Get the LineTranslateAnchor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getLineTranslateAnchor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetLineTranslateAnchor());
+ }
+
+ /**
+ * Get the LineWidth property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getLineWidth() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetLineWidth());
+ }
+
+ /**
+ * Get the LineGapWidth property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getLineGapWidth() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetLineGapWidth());
+ }
+
+ /**
+ * Get the LineOffset property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getLineOffset() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetLineOffset());
+ }
+
+ /**
+ * Get the LineBlur property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getLineBlur() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetLineBlur());
+ }
+
+ /**
+ * Get the LineDasharray property
+ *
+ * @return property wrapper value around Float[]
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float[]> getLineDasharray() {
+ return (PropertyValue<Float[]>) new PropertyValue(nativeGetLineDasharray());
+ }
+
+ /**
+ * Get the LinePattern property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getLinePattern() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetLinePattern());
+ }
+
+ private native Object nativeGetLineCap();
+
+ private native Object nativeGetLineJoin();
+
+ private native Object nativeGetLineMiterLimit();
+
+ private native Object nativeGetLineRoundLimit();
+
+ private native Object nativeGetLineOpacity();
+
+ private native Object nativeGetLineColor();
+
+ private native Object nativeGetLineTranslate();
+
+ private native Object nativeGetLineTranslateAnchor();
+
+ private native Object nativeGetLineWidth();
+
+ private native Object nativeGetLineGapWidth();
+
+ private native Object nativeGetLineOffset();
+
+ private native Object nativeGetLineBlur();
+
+ private native Object nativeGetLineDasharray();
+
+ private native Object nativeGetLinePattern();
+
+
+ @Override
+ protected native void finalize() throws Throwable;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/NoSuchLayerException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/NoSuchLayerException.java
index d6ef4f8824..3b8777080d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/NoSuchLayerException.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/NoSuchLayerException.java
@@ -5,7 +5,7 @@ package com.mapbox.mapboxsdk.style.layers;
*/
public class NoSuchLayerException extends Exception {
- public NoSuchLayerException(String message) {
- super(message);
- }
+ public NoSuchLayerException(String message) {
+ super(message);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PaintProperty.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PaintProperty.java
index 6f1a9a0a16..69405177d9 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PaintProperty.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PaintProperty.java
@@ -2,8 +2,8 @@ package com.mapbox.mapboxsdk.style.layers;
class PaintProperty<T> extends Property<T> {
- PaintProperty(String name, T value) {
- super(name, value);
- }
+ PaintProperty(String name, T value) {
+ super(name, value);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
index 383d4217a8..bb060ddf15 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
@@ -1,5 +1,5 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
import android.support.annotation.StringDef;
@@ -11,448 +11,477 @@ import java.lang.annotation.RetentionPolicy;
*/
public abstract class Property<T> {
- //VISIBILITY: Whether this layer is displayed.
-
- /**
- * The layer is shown.
- */
- public static final String VISIBLE = "visible";
- /**
- * The layer is hidden.
- */
- public static final String NONE = "none";
-
- @StringDef({
- VISIBLE,
- NONE
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface VISIBILITY {}
-
- //LINE_CAP: The display of line endings.
-
- /**
- * A cap with a squared-off end which is drawn to the exact endpoint of the line.
- */
- public static final String LINE_CAP_BUTT = "butt";
- /**
- * A cap with a rounded end which is drawn beyond the endpoint of the line at a radius of one-half of the line's width and centered on the endpoint of the line.
- */
- public static final String LINE_CAP_ROUND = "round";
- /**
- * A cap with a squared-off end which is drawn beyond the endpoint of the line at a distance of one-half of the line's width.
- */
- public static final String LINE_CAP_SQUARE = "square";
-
- /**
- * The display of line endings.
- */
- @StringDef({
- LINE_CAP_BUTT,
- LINE_CAP_ROUND,
- LINE_CAP_SQUARE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface LINE_CAP {}
-
- //LINE_JOIN: The display of lines when joining.
-
- /**
- * A join with a squared-off end which is drawn beyond the endpoint of the line at a distance of one-half of the line's width.
- */
- public static final String LINE_JOIN_BEVEL = "bevel";
- /**
- * A join with a rounded end which is drawn beyond the endpoint of the line at a radius of one-half of the line's width and centered on the endpoint of the line.
- */
- public static final String LINE_JOIN_ROUND = "round";
- /**
- * A join with a sharp, angled corner which is drawn with the outer sides beyond the endpoint of the path until they meet.
- */
- public static final String LINE_JOIN_MITER = "miter";
-
- /**
- * The display of lines when joining.
- */
- @StringDef({
- LINE_JOIN_BEVEL,
- LINE_JOIN_ROUND,
- LINE_JOIN_MITER,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface LINE_JOIN {}
-
- //SYMBOL_PLACEMENT: Label placement relative to its geometry.
-
- /**
- * The label is placed at the point where the geometry is located.
- */
- public static final String SYMBOL_PLACEMENT_POINT = "point";
- /**
- * The label is placed along the line of the geometry. Can only be used on LineString and Polygon geometries.
- */
- public static final String SYMBOL_PLACEMENT_LINE = "line";
-
- /**
- * Label placement relative to its geometry.
- */
- @StringDef({
- SYMBOL_PLACEMENT_POINT,
- SYMBOL_PLACEMENT_LINE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface SYMBOL_PLACEMENT {}
-
- //ICON_ROTATION_ALIGNMENT: In combination with `symbol-placement`, determines the rotation behavior of icons.
-
- /**
- * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, aligns icons east-west. When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_LINE}, aligns icon x-axes with the line.
- */
- public static final String ICON_ROTATION_ALIGNMENT_MAP = "map";
- /**
- * Produces icons whose x-axes are aligned with the x-axis of the viewport, regardless of the value of {@link SYMBOL_PLACEMENT}.
- */
- public static final String ICON_ROTATION_ALIGNMENT_VIEWPORT = "viewport";
- /**
- * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, this is equivalent to {@link Property#ICON_ROTATION_ALIGNMENT_VIEWPORT}. When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_LINE}, this is equivalent to {@link Property#ICON_ROTATION_ALIGNMENT_MAP}.
- */
- public static final String ICON_ROTATION_ALIGNMENT_AUTO = "auto";
-
- /**
- * In combination with `symbol-placement`, determines the rotation behavior of icons.
- */
- @StringDef({
- ICON_ROTATION_ALIGNMENT_MAP,
- ICON_ROTATION_ALIGNMENT_VIEWPORT,
- ICON_ROTATION_ALIGNMENT_AUTO,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ICON_ROTATION_ALIGNMENT {}
-
- //ICON_TEXT_FIT: Scales the icon to fit around the associated text.
-
- /**
- * The icon is displayed at its intrinsic aspect ratio.
- */
- public static final String ICON_TEXT_FIT_NONE = "none";
- /**
- * The icon is scaled in the x-dimension to fit the width of the text.
- */
- public static final String ICON_TEXT_FIT_WIDTH = "width";
- /**
- * The icon is scaled in the y-dimension to fit the height of the text.
- */
- public static final String ICON_TEXT_FIT_HEIGHT = "height";
- /**
- * The icon is scaled in both x- and y-dimensions.
- */
- public static final String ICON_TEXT_FIT_BOTH = "both";
-
- /**
- * Scales the icon to fit around the associated text.
- */
- @StringDef({
- ICON_TEXT_FIT_NONE,
- ICON_TEXT_FIT_WIDTH,
- ICON_TEXT_FIT_HEIGHT,
- ICON_TEXT_FIT_BOTH,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ICON_TEXT_FIT {}
-
- //TEXT_PITCH_ALIGNMENT: Orientation of text when map is pitched.
-
- /**
- * The text is aligned to the plane of the map.
- */
- public static final String TEXT_PITCH_ALIGNMENT_MAP = "map";
- /**
- * The text is aligned to the plane of the viewport.
- */
- public static final String TEXT_PITCH_ALIGNMENT_VIEWPORT = "viewport";
- /**
- * Automatically matches the value of {@link TEXT_ROTATION_ALIGNMENT}.
- */
- public static final String TEXT_PITCH_ALIGNMENT_AUTO = "auto";
-
- /**
- * Orientation of text when map is pitched.
- */
- @StringDef({
- TEXT_PITCH_ALIGNMENT_MAP,
- TEXT_PITCH_ALIGNMENT_VIEWPORT,
- TEXT_PITCH_ALIGNMENT_AUTO,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TEXT_PITCH_ALIGNMENT {}
-
- //TEXT_ROTATION_ALIGNMENT: In combination with `symbol-placement`, determines the rotation behavior of the individual glyphs forming the text.
-
- /**
- * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, aligns text east-west. When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_LINE}, aligns text x-axes with the line.
- */
- public static final String TEXT_ROTATION_ALIGNMENT_MAP = "map";
- /**
- * Produces glyphs whose x-axes are aligned with the x-axis of the viewport, regardless of the value of {@link SYMBOL_PLACEMENT}.
- */
- public static final String TEXT_ROTATION_ALIGNMENT_VIEWPORT = "viewport";
- /**
- * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, this is equivalent to {@link Property#TEXT_ROTATION_ALIGNMENT_VIEWPORT}. When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_LINE}, this is equivalent to {@link Property#TEXT_ROTATION_ALIGNMENT_MAP}.
- */
- public static final String TEXT_ROTATION_ALIGNMENT_AUTO = "auto";
-
- /**
- * In combination with `symbol-placement`, determines the rotation behavior of the individual glyphs forming the text.
- */
- @StringDef({
- TEXT_ROTATION_ALIGNMENT_MAP,
- TEXT_ROTATION_ALIGNMENT_VIEWPORT,
- TEXT_ROTATION_ALIGNMENT_AUTO,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TEXT_ROTATION_ALIGNMENT {}
-
- //TEXT_JUSTIFY: Text justification options.
-
- /**
- * The text is aligned to the left.
- */
- public static final String TEXT_JUSTIFY_LEFT = "left";
- /**
- * The text is centered.
- */
- public static final String TEXT_JUSTIFY_CENTER = "center";
- /**
- * The text is aligned to the right.
- */
- public static final String TEXT_JUSTIFY_RIGHT = "right";
-
- /**
- * Text justification options.
- */
- @StringDef({
- TEXT_JUSTIFY_LEFT,
- TEXT_JUSTIFY_CENTER,
- TEXT_JUSTIFY_RIGHT,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TEXT_JUSTIFY {}
-
- //TEXT_ANCHOR: Part of the text placed closest to the anchor.
-
- /**
- * The center of the text is placed closest to the anchor.
- */
- public static final String TEXT_ANCHOR_CENTER = "center";
- /**
- * The left side of the text is placed closest to the anchor.
- */
- public static final String TEXT_ANCHOR_LEFT = "left";
- /**
- * The right side of the text is placed closest to the anchor.
- */
- public static final String TEXT_ANCHOR_RIGHT = "right";
- /**
- * The top of the text is placed closest to the anchor.
- */
- public static final String TEXT_ANCHOR_TOP = "top";
- /**
- * The bottom of the text is placed closest to the anchor.
- */
- public static final String TEXT_ANCHOR_BOTTOM = "bottom";
- /**
- * The top left corner of the text is placed closest to the anchor.
- */
- public static final String TEXT_ANCHOR_TOP_LEFT = "top-left";
- /**
- * The top right corner of the text is placed closest to the anchor.
- */
- public static final String TEXT_ANCHOR_TOP_RIGHT = "top-right";
- /**
- * The bottom left corner of the text is placed closest to the anchor.
- */
- public static final String TEXT_ANCHOR_BOTTOM_LEFT = "bottom-left";
- /**
- * The bottom right corner of the text is placed closest to the anchor.
- */
- public static final String TEXT_ANCHOR_BOTTOM_RIGHT = "bottom-right";
-
- /**
- * Part of the text placed closest to the anchor.
- */
- @StringDef({
- TEXT_ANCHOR_CENTER,
- TEXT_ANCHOR_LEFT,
- TEXT_ANCHOR_RIGHT,
- TEXT_ANCHOR_TOP,
- TEXT_ANCHOR_BOTTOM,
- TEXT_ANCHOR_TOP_LEFT,
- TEXT_ANCHOR_TOP_RIGHT,
- TEXT_ANCHOR_BOTTOM_LEFT,
- TEXT_ANCHOR_BOTTOM_RIGHT,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TEXT_ANCHOR {}
-
- //TEXT_TRANSFORM: Specifies how to capitalize text, similar to the CSS `text-transform` property.
-
- /**
- * The text is not altered.
- */
- public static final String TEXT_TRANSFORM_NONE = "none";
- /**
- * Forces all letters to be displayed in uppercase.
- */
- public static final String TEXT_TRANSFORM_UPPERCASE = "uppercase";
- /**
- * Forces all letters to be displayed in lowercase.
- */
- public static final String TEXT_TRANSFORM_LOWERCASE = "lowercase";
-
- /**
- * Specifies how to capitalize text, similar to the CSS `text-transform` property.
- */
- @StringDef({
- TEXT_TRANSFORM_NONE,
- TEXT_TRANSFORM_UPPERCASE,
- TEXT_TRANSFORM_LOWERCASE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TEXT_TRANSFORM {}
-
- //FILL_TRANSLATE_ANCHOR: Controls the translation reference point.
-
- /**
- * The fill is translated relative to the map.
- */
- public static final String FILL_TRANSLATE_ANCHOR_MAP = "map";
- /**
- * The fill is translated relative to the viewport.
- */
- public static final String FILL_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
-
- /**
- * Controls the translation reference point.
- */
- @StringDef({
- FILL_TRANSLATE_ANCHOR_MAP,
- FILL_TRANSLATE_ANCHOR_VIEWPORT,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface FILL_TRANSLATE_ANCHOR {}
-
- //LINE_TRANSLATE_ANCHOR: Controls the translation reference point.
-
- /**
- * The line is translated relative to the map.
- */
- public static final String LINE_TRANSLATE_ANCHOR_MAP = "map";
- /**
- * The line is translated relative to the viewport.
- */
- public static final String LINE_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
-
- /**
- * Controls the translation reference point.
- */
- @StringDef({
- LINE_TRANSLATE_ANCHOR_MAP,
- LINE_TRANSLATE_ANCHOR_VIEWPORT,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface LINE_TRANSLATE_ANCHOR {}
-
- //ICON_TRANSLATE_ANCHOR: Controls the translation reference point.
-
- /**
- * Icons are translated relative to the map.
- */
- public static final String ICON_TRANSLATE_ANCHOR_MAP = "map";
- /**
- * Icons are translated relative to the viewport.
- */
- public static final String ICON_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
-
- /**
- * Controls the translation reference point.
- */
- @StringDef({
- ICON_TRANSLATE_ANCHOR_MAP,
- ICON_TRANSLATE_ANCHOR_VIEWPORT,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ICON_TRANSLATE_ANCHOR {}
-
- //TEXT_TRANSLATE_ANCHOR: Controls the translation reference point.
-
- /**
- * The text is translated relative to the map.
- */
- public static final String TEXT_TRANSLATE_ANCHOR_MAP = "map";
- /**
- * The text is translated relative to the viewport.
- */
- public static final String TEXT_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
-
- /**
- * Controls the translation reference point.
- */
- @StringDef({
- TEXT_TRANSLATE_ANCHOR_MAP,
- TEXT_TRANSLATE_ANCHOR_VIEWPORT,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TEXT_TRANSLATE_ANCHOR {}
-
- //CIRCLE_TRANSLATE_ANCHOR: Controls the translation reference point.
-
- /**
- * The circle is translated relative to the map.
- */
- public static final String CIRCLE_TRANSLATE_ANCHOR_MAP = "map";
- /**
- * The circle is translated relative to the viewport.
- */
- public static final String CIRCLE_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
-
- /**
- * Controls the translation reference point.
- */
- @StringDef({
- CIRCLE_TRANSLATE_ANCHOR_MAP,
- CIRCLE_TRANSLATE_ANCHOR_VIEWPORT,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface CIRCLE_TRANSLATE_ANCHOR {}
-
- //CIRCLE_PITCH_SCALE: Controls the scaling behavior of the circle when the map is pitched.
-
- /**
- * Circles are scaled according to their apparent distance to the camera.
- */
- public static final String CIRCLE_PITCH_SCALE_MAP = "map";
- /**
- * Circles are not scaled.
- */
- public static final String CIRCLE_PITCH_SCALE_VIEWPORT = "viewport";
-
- /**
- * Controls the scaling behavior of the circle when the map is pitched.
- */
- @StringDef({
- CIRCLE_PITCH_SCALE_MAP,
- CIRCLE_PITCH_SCALE_VIEWPORT,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface CIRCLE_PITCH_SCALE {}
-
-
- //Class definition
- public final String name;
- public final T value;
-
- /* package */ Property(String name, T value) {
- this.name = name;
- this.value = value;
- }
-
+ //VISIBILITY: Whether this layer is displayed.
+
+ /**
+ * The layer is shown.
+ */
+ public static final String VISIBLE = "visible";
+ /**
+ * The layer is hidden.
+ */
+ public static final String NONE = "none";
+
+ @StringDef( {
+ VISIBLE,
+ NONE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VISIBILITY {
+ }
+
+ //LINE_CAP: The display of line endings.
+
+ /**
+ * A cap with a squared-off end which is drawn to the exact endpoint of the line.
+ */
+ public static final String LINE_CAP_BUTT = "butt";
+ /**
+ * A cap with a rounded end which is drawn beyond the endpoint of the line at a radius of one-half of the line's
+ * width and centered on the endpoint of the line.
+ */
+ public static final String LINE_CAP_ROUND = "round";
+ /**
+ * A cap with a squared-off end which is drawn beyond the endpoint of the line at a distance of one-half of the
+ * line's width.
+ */
+ public static final String LINE_CAP_SQUARE = "square";
+
+ /**
+ * The display of line endings.
+ */
+ @StringDef( {
+ LINE_CAP_BUTT,
+ LINE_CAP_ROUND,
+ LINE_CAP_SQUARE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LINE_CAP {
+ }
+
+ //LINE_JOIN: The display of lines when joining.
+
+ /**
+ * A join with a squared-off end which is drawn beyond the endpoint of the line at a distance of one-half of the
+ * line's width.
+ */
+ public static final String LINE_JOIN_BEVEL = "bevel";
+ /**
+ * A join with a rounded end which is drawn beyond the endpoint of the line at a radius of one-half of the line's
+ * width and centered on the endpoint of the line.
+ */
+ public static final String LINE_JOIN_ROUND = "round";
+ /**
+ * A join with a sharp, angled corner which is drawn with the outer sides beyond the endpoint of the path until
+ * they meet.
+ */
+ public static final String LINE_JOIN_MITER = "miter";
+
+ /**
+ * The display of lines when joining.
+ */
+ @StringDef( {
+ LINE_JOIN_BEVEL,
+ LINE_JOIN_ROUND,
+ LINE_JOIN_MITER,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LINE_JOIN {
+ }
+
+ //SYMBOL_PLACEMENT: Label placement relative to its geometry.
+
+ /**
+ * The label is placed at the point where the geometry is located.
+ */
+ public static final String SYMBOL_PLACEMENT_POINT = "point";
+ /**
+ * The label is placed along the line of the geometry. Can only be used on LineString and Polygon geometries.
+ */
+ public static final String SYMBOL_PLACEMENT_LINE = "line";
+
+ /**
+ * Label placement relative to its geometry.
+ */
+ @StringDef( {
+ SYMBOL_PLACEMENT_POINT,
+ SYMBOL_PLACEMENT_LINE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SYMBOL_PLACEMENT {
+ }
+
+ //ICON_ROTATION_ALIGNMENT: In combination with `symbol-placement`, determines the rotation behavior of icons.
+
+ /**
+ * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, aligns icons east-west. When
+ * {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_LINE}, aligns icon x-axes with the line.
+ */
+ public static final String ICON_ROTATION_ALIGNMENT_MAP = "map";
+ /**
+ * Produces icons whose x-axes are aligned with the x-axis of the viewport, regardless of the value of
+ * {@link SYMBOL_PLACEMENT}.
+ */
+ public static final String ICON_ROTATION_ALIGNMENT_VIEWPORT = "viewport";
+ /**
+ * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, this is equivalent to
+ * {@link Property#ICON_ROTATION_ALIGNMENT_VIEWPORT}. When {@link SYMBOL_PLACEMENT} is set to
+ * {@link Property#SYMBOL_PLACEMENT_LINE}, this is equivalent to {@link Property#ICON_ROTATION_ALIGNMENT_MAP}.
+ */
+ public static final String ICON_ROTATION_ALIGNMENT_AUTO = "auto";
+
+ /**
+ * In combination with `symbol-placement`, determines the rotation behavior of icons.
+ */
+ @StringDef( {
+ ICON_ROTATION_ALIGNMENT_MAP,
+ ICON_ROTATION_ALIGNMENT_VIEWPORT,
+ ICON_ROTATION_ALIGNMENT_AUTO,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ICON_ROTATION_ALIGNMENT {
+ }
+
+ //ICON_TEXT_FIT: Scales the icon to fit around the associated text.
+
+ /**
+ * The icon is displayed at its intrinsic aspect ratio.
+ */
+ public static final String ICON_TEXT_FIT_NONE = "none";
+ /**
+ * The icon is scaled in the x-dimension to fit the width of the text.
+ */
+ public static final String ICON_TEXT_FIT_WIDTH = "width";
+ /**
+ * The icon is scaled in the y-dimension to fit the height of the text.
+ */
+ public static final String ICON_TEXT_FIT_HEIGHT = "height";
+ /**
+ * The icon is scaled in both x- and y-dimensions.
+ */
+ public static final String ICON_TEXT_FIT_BOTH = "both";
+
+ /**
+ * Scales the icon to fit around the associated text.
+ */
+ @StringDef( {
+ ICON_TEXT_FIT_NONE,
+ ICON_TEXT_FIT_WIDTH,
+ ICON_TEXT_FIT_HEIGHT,
+ ICON_TEXT_FIT_BOTH,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ICON_TEXT_FIT {
+ }
+
+ //TEXT_PITCH_ALIGNMENT: Orientation of text when map is pitched.
+
+ /**
+ * The text is aligned to the plane of the map.
+ */
+ public static final String TEXT_PITCH_ALIGNMENT_MAP = "map";
+ /**
+ * The text is aligned to the plane of the viewport.
+ */
+ public static final String TEXT_PITCH_ALIGNMENT_VIEWPORT = "viewport";
+ /**
+ * Automatically matches the value of {@link TEXT_ROTATION_ALIGNMENT}.
+ */
+ public static final String TEXT_PITCH_ALIGNMENT_AUTO = "auto";
+
+ /**
+ * Orientation of text when map is pitched.
+ */
+ @StringDef( {
+ TEXT_PITCH_ALIGNMENT_MAP,
+ TEXT_PITCH_ALIGNMENT_VIEWPORT,
+ TEXT_PITCH_ALIGNMENT_AUTO,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TEXT_PITCH_ALIGNMENT {
+ }
+
+ //TEXT_ROTATION_ALIGNMENT: In combination with `symbol-placement`, determines the rotation behavior of the individual
+ // glyphs forming the text.
+
+ /**
+ * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, aligns text east-west. When
+ * {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_LINE}, aligns text x-axes with the line.
+ */
+ public static final String TEXT_ROTATION_ALIGNMENT_MAP = "map";
+ /**
+ * Produces glyphs whose x-axes are aligned with the x-axis of the viewport, regardless of the value of
+ * {@link SYMBOL_PLACEMENT}.
+ */
+ public static final String TEXT_ROTATION_ALIGNMENT_VIEWPORT = "viewport";
+ /**
+ * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, this is equivalent to
+ * {@link Property#TEXT_ROTATION_ALIGNMENT_VIEWPORT}. When {@link SYMBOL_PLACEMENT} is set to
+ * {@link Property#SYMBOL_PLACEMENT_LINE}, this is equivalent to {@link Property#TEXT_ROTATION_ALIGNMENT_MAP}.
+ */
+ public static final String TEXT_ROTATION_ALIGNMENT_AUTO = "auto";
+
+ /**
+ * In combination with `symbol-placement`, determines the rotation behavior of the individual glyphs forming the text.
+ */
+ @StringDef( {
+ TEXT_ROTATION_ALIGNMENT_MAP,
+ TEXT_ROTATION_ALIGNMENT_VIEWPORT,
+ TEXT_ROTATION_ALIGNMENT_AUTO,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TEXT_ROTATION_ALIGNMENT {
+ }
+
+ //TEXT_JUSTIFY: Text justification options.
+
+ /**
+ * The text is aligned to the left.
+ */
+ public static final String TEXT_JUSTIFY_LEFT = "left";
+ /**
+ * The text is centered.
+ */
+ public static final String TEXT_JUSTIFY_CENTER = "center";
+ /**
+ * The text is aligned to the right.
+ */
+ public static final String TEXT_JUSTIFY_RIGHT = "right";
+
+ /**
+ * Text justification options.
+ */
+ @StringDef( {
+ TEXT_JUSTIFY_LEFT,
+ TEXT_JUSTIFY_CENTER,
+ TEXT_JUSTIFY_RIGHT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TEXT_JUSTIFY {
+ }
+
+ //TEXT_ANCHOR: Part of the text placed closest to the anchor.
+
+ /**
+ * The center of the text is placed closest to the anchor.
+ */
+ public static final String TEXT_ANCHOR_CENTER = "center";
+ /**
+ * The left side of the text is placed closest to the anchor.
+ */
+ public static final String TEXT_ANCHOR_LEFT = "left";
+ /**
+ * The right side of the text is placed closest to the anchor.
+ */
+ public static final String TEXT_ANCHOR_RIGHT = "right";
+ /**
+ * The top of the text is placed closest to the anchor.
+ */
+ public static final String TEXT_ANCHOR_TOP = "top";
+ /**
+ * The bottom of the text is placed closest to the anchor.
+ */
+ public static final String TEXT_ANCHOR_BOTTOM = "bottom";
+ /**
+ * The top left corner of the text is placed closest to the anchor.
+ */
+ public static final String TEXT_ANCHOR_TOP_LEFT = "top-left";
+ /**
+ * The top right corner of the text is placed closest to the anchor.
+ */
+ public static final String TEXT_ANCHOR_TOP_RIGHT = "top-right";
+ /**
+ * The bottom left corner of the text is placed closest to the anchor.
+ */
+ public static final String TEXT_ANCHOR_BOTTOM_LEFT = "bottom-left";
+ /**
+ * The bottom right corner of the text is placed closest to the anchor.
+ */
+ public static final String TEXT_ANCHOR_BOTTOM_RIGHT = "bottom-right";
+
+ /**
+ * Part of the text placed closest to the anchor.
+ */
+ @StringDef( {
+ TEXT_ANCHOR_CENTER,
+ TEXT_ANCHOR_LEFT,
+ TEXT_ANCHOR_RIGHT,
+ TEXT_ANCHOR_TOP,
+ TEXT_ANCHOR_BOTTOM,
+ TEXT_ANCHOR_TOP_LEFT,
+ TEXT_ANCHOR_TOP_RIGHT,
+ TEXT_ANCHOR_BOTTOM_LEFT,
+ TEXT_ANCHOR_BOTTOM_RIGHT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TEXT_ANCHOR {
+ }
+
+ //TEXT_TRANSFORM: Specifies how to capitalize text, similar to the CSS `text-transform` property.
+
+ /**
+ * The text is not altered.
+ */
+ public static final String TEXT_TRANSFORM_NONE = "none";
+ /**
+ * Forces all letters to be displayed in uppercase.
+ */
+ public static final String TEXT_TRANSFORM_UPPERCASE = "uppercase";
+ /**
+ * Forces all letters to be displayed in lowercase.
+ */
+ public static final String TEXT_TRANSFORM_LOWERCASE = "lowercase";
+
+ /**
+ * Specifies how to capitalize text, similar to the CSS `text-transform` property.
+ */
+ @StringDef( {
+ TEXT_TRANSFORM_NONE,
+ TEXT_TRANSFORM_UPPERCASE,
+ TEXT_TRANSFORM_LOWERCASE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TEXT_TRANSFORM {
+ }
+
+ //FILL_TRANSLATE_ANCHOR: Controls the translation reference point.
+
+ /**
+ * The fill is translated relative to the map.
+ */
+ public static final String FILL_TRANSLATE_ANCHOR_MAP = "map";
+ /**
+ * The fill is translated relative to the viewport.
+ */
+ public static final String FILL_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
+
+ /**
+ * Controls the translation reference point.
+ */
+ @StringDef( {
+ FILL_TRANSLATE_ANCHOR_MAP,
+ FILL_TRANSLATE_ANCHOR_VIEWPORT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FILL_TRANSLATE_ANCHOR {
+ }
+
+ //LINE_TRANSLATE_ANCHOR: Controls the translation reference point.
+
+ /**
+ * The line is translated relative to the map.
+ */
+ public static final String LINE_TRANSLATE_ANCHOR_MAP = "map";
+ /**
+ * The line is translated relative to the viewport.
+ */
+ public static final String LINE_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
+
+ /**
+ * Controls the translation reference point.
+ */
+ @StringDef( {
+ LINE_TRANSLATE_ANCHOR_MAP,
+ LINE_TRANSLATE_ANCHOR_VIEWPORT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LINE_TRANSLATE_ANCHOR {
+ }
+
+ //ICON_TRANSLATE_ANCHOR: Controls the translation reference point.
+
+ /**
+ * Icons are translated relative to the map.
+ */
+ public static final String ICON_TRANSLATE_ANCHOR_MAP = "map";
+ /**
+ * Icons are translated relative to the viewport.
+ */
+ public static final String ICON_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
+
+ /**
+ * Controls the translation reference point.
+ */
+ @StringDef( {
+ ICON_TRANSLATE_ANCHOR_MAP,
+ ICON_TRANSLATE_ANCHOR_VIEWPORT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ICON_TRANSLATE_ANCHOR {
+ }
+
+ //TEXT_TRANSLATE_ANCHOR: Controls the translation reference point.
+
+ /**
+ * The text is translated relative to the map.
+ */
+ public static final String TEXT_TRANSLATE_ANCHOR_MAP = "map";
+ /**
+ * The text is translated relative to the viewport.
+ */
+ public static final String TEXT_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
+
+ /**
+ * Controls the translation reference point.
+ */
+ @StringDef( {
+ TEXT_TRANSLATE_ANCHOR_MAP,
+ TEXT_TRANSLATE_ANCHOR_VIEWPORT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TEXT_TRANSLATE_ANCHOR {
+ }
+
+ //CIRCLE_TRANSLATE_ANCHOR: Controls the translation reference point.
+
+ /**
+ * The circle is translated relative to the map.
+ */
+ public static final String CIRCLE_TRANSLATE_ANCHOR_MAP = "map";
+ /**
+ * The circle is translated relative to the viewport.
+ */
+ public static final String CIRCLE_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
+
+ /**
+ * Controls the translation reference point.
+ */
+ @StringDef( {
+ CIRCLE_TRANSLATE_ANCHOR_MAP,
+ CIRCLE_TRANSLATE_ANCHOR_VIEWPORT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CIRCLE_TRANSLATE_ANCHOR {
+ }
+
+ //CIRCLE_PITCH_SCALE: Controls the scaling behavior of the circle when the map is pitched.
+
+ /**
+ * Circles are scaled according to their apparent distance to the camera.
+ */
+ public static final String CIRCLE_PITCH_SCALE_MAP = "map";
+ /**
+ * Circles are not scaled.
+ */
+ public static final String CIRCLE_PITCH_SCALE_VIEWPORT = "viewport";
+
+ /**
+ * Controls the scaling behavior of the circle when the map is pitched.
+ */
+ @StringDef( {
+ CIRCLE_PITCH_SCALE_MAP,
+ CIRCLE_PITCH_SCALE_VIEWPORT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CIRCLE_PITCH_SCALE {
+ }
+
+ //Class definition
+ public final String name;
+ public final T value;
+
+ /* package */ Property(String name, T value) {
+ this.name = name;
+ this.value = value;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
index 0cb8fdeff9..8e7d516a39 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
@@ -1,5 +1,5 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
import android.annotation.SuppressLint;
import android.support.annotation.ColorInt;
@@ -11,1839 +11,1947 @@ import android.support.annotation.ColorInt;
*/
public class PropertyFactory {
- /**
- * Set the property visibility.
- *
- * @param value the visibility value
- * @return property wrapper around visibility
- */
- public static Property<String> visibility(@Property.VISIBILITY String value) {
- return new LayoutProperty<>("visibility", value);
- }
-
- /**
- * Set the property visibility.
- *
- * @param function the visibility function
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> visibility(Function<String> function) {
- return new LayoutProperty<>("visibility", function);
- }
-
- /**
- * Whether or not the fill should be antialiased.
- *
- * @param value a Boolean value
- * @return property wrapper around Boolean
- */
- public static Property<Boolean> fillAntialias(Boolean value) {
- return new PaintProperty<>("fill-antialias", value);
- }
-
- /**
- * Whether or not the fill should be antialiased.
- *
- * @param function a wrapper function for Boolean
- * @return property wrapper around a Boolean function
- */
- public static Property<Function<Boolean>> fillAntialias(Function<Boolean> function) {
- return new PaintProperty<>("fill-antialias", function);
- }
-
- /**
- * The opacity of the entire fill layer. In contrast to the {@link PropertyFactory#fillColor}, this value will also affect the 1px stroke around the fill, if the stroke is used.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> fillOpacity(Float value) {
- return new PaintProperty<>("fill-opacity", value);
- }
-
- /**
- * The opacity of the entire fill layer. In contrast to the {@link PropertyFactory#fillColor}, this value will also affect the 1px stroke around the fill, if the stroke is used.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> fillOpacity(Function<Float> function) {
- return new PaintProperty<>("fill-opacity", function);
- }
-
- /**
- * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the color's opacity will not affect the opacity of the 1px stroke, if it is used.
- *
- * @param value a int color value
- * @return property wrapper around String color
- */
- public static Property<String> fillColor(@ColorInt int value) {
- return new PaintProperty<>("fill-color", colorToRgbaString(value));
- }
-
- /**
- * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the color's opacity will not affect the opacity of the 1px stroke, if it is used.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> fillColor(String value) {
- return new PaintProperty<>("fill-color", value);
- }
-
- /**
- * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the color's opacity will not affect the opacity of the 1px stroke, if it is used.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> fillColor(Function<String> function) {
- return new PaintProperty<>("fill-color", function);
- }
-
- /**
- * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified.
- *
- * @param value a int color value
- * @return property wrapper around String color
- */
- public static Property<String> fillOutlineColor(@ColorInt int value) {
- return new PaintProperty<>("fill-outline-color", colorToRgbaString(value));
- }
-
- /**
- * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> fillOutlineColor(String value) {
- return new PaintProperty<>("fill-outline-color", value);
- }
-
- /**
- * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> fillOutlineColor(Function<String> function) {
- return new PaintProperty<>("fill-outline-color", function);
- }
-
- /**
- * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
- *
- * @param value a Float[] value
- * @return property wrapper around Float[]
- */
- public static Property<Float[]> fillTranslate(Float[] value) {
- return new PaintProperty<>("fill-translate", value);
- }
-
- /**
- * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
- *
- * @param function a wrapper function for Float[]
- * @return property wrapper around a Float[] function
- */
- public static Property<Function<Float[]>> fillTranslate(Function<Float[]> function) {
- return new PaintProperty<>("fill-translate", function);
- }
-
- /**
- * Controls the translation reference point.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> fillTranslateAnchor(@Property.FILL_TRANSLATE_ANCHOR String value) {
- return new PaintProperty<>("fill-translate-anchor", value);
- }
-
- /**
- * Controls the translation reference point.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> fillTranslateAnchor(Function<String> function) {
- return new PaintProperty<>("fill-translate-anchor", function);
- }
-
- /**
- * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> fillPattern(String value) {
- return new PaintProperty<>("fill-pattern", value);
- }
-
- /**
- * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> fillPattern(Function<String> function) {
- return new PaintProperty<>("fill-pattern", function);
- }
-
- /**
- * The opacity at which the line will be drawn.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> lineOpacity(Float value) {
- return new PaintProperty<>("line-opacity", value);
- }
-
- /**
- * The opacity at which the line will be drawn.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> lineOpacity(Function<Float> function) {
- return new PaintProperty<>("line-opacity", function);
- }
-
- /**
- * The color with which the line will be drawn.
- *
- * @param value a int color value
- * @return property wrapper around String color
- */
- public static Property<String> lineColor(@ColorInt int value) {
- return new PaintProperty<>("line-color", colorToRgbaString(value));
- }
-
- /**
- * The color with which the line will be drawn.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> lineColor(String value) {
- return new PaintProperty<>("line-color", value);
- }
-
- /**
- * The color with which the line will be drawn.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> lineColor(Function<String> function) {
- return new PaintProperty<>("line-color", function);
- }
-
- /**
- * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
- *
- * @param value a Float[] value
- * @return property wrapper around Float[]
- */
- public static Property<Float[]> lineTranslate(Float[] value) {
- return new PaintProperty<>("line-translate", value);
- }
-
- /**
- * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
- *
- * @param function a wrapper function for Float[]
- * @return property wrapper around a Float[] function
- */
- public static Property<Function<Float[]>> lineTranslate(Function<Float[]> function) {
- return new PaintProperty<>("line-translate", function);
- }
-
- /**
- * Controls the translation reference point.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> lineTranslateAnchor(@Property.LINE_TRANSLATE_ANCHOR String value) {
- return new PaintProperty<>("line-translate-anchor", value);
- }
-
- /**
- * Controls the translation reference point.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> lineTranslateAnchor(Function<String> function) {
- return new PaintProperty<>("line-translate-anchor", function);
- }
-
- /**
- * Stroke thickness.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> lineWidth(Float value) {
- return new PaintProperty<>("line-width", value);
- }
-
- /**
- * Stroke thickness.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> lineWidth(Function<Float> function) {
- return new PaintProperty<>("line-width", function);
- }
-
- /**
- * Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> lineGapWidth(Float value) {
- return new PaintProperty<>("line-gap-width", value);
- }
-
- /**
- * Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> lineGapWidth(Function<Float> function) {
- return new PaintProperty<>("line-gap-width", function);
- }
-
- /**
- * The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a negative value results in an outset.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> lineOffset(Float value) {
- return new PaintProperty<>("line-offset", value);
- }
-
- /**
- * The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a negative value results in an outset.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> lineOffset(Function<Float> function) {
- return new PaintProperty<>("line-offset", function);
- }
-
- /**
- * Blur applied to the line, in pixels.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> lineBlur(Float value) {
- return new PaintProperty<>("line-blur", value);
- }
-
- /**
- * Blur applied to the line, in pixels.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> lineBlur(Function<Float> function) {
- return new PaintProperty<>("line-blur", function);
- }
-
- /**
- * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to pixels, multiply the length by the current line width.
- *
- * @param value a Float[] value
- * @return property wrapper around Float[]
- */
- public static Property<Float[]> lineDasharray(Float[] value) {
- return new PaintProperty<>("line-dasharray", value);
- }
-
- /**
- * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to pixels, multiply the length by the current line width.
- *
- * @param function a wrapper function for Float[]
- * @return property wrapper around a Float[] function
- */
- public static Property<Function<Float[]>> lineDasharray(Function<Float[]> function) {
- return new PaintProperty<>("line-dasharray", function);
- }
-
- /**
- * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512).
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> linePattern(String value) {
- return new PaintProperty<>("line-pattern", value);
- }
-
- /**
- * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512).
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> linePattern(Function<String> function) {
- return new PaintProperty<>("line-pattern", function);
- }
-
- /**
- * The opacity at which the icon will be drawn.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> iconOpacity(Float value) {
- return new PaintProperty<>("icon-opacity", value);
- }
-
- /**
- * The opacity at which the icon will be drawn.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> iconOpacity(Function<Float> function) {
- return new PaintProperty<>("icon-opacity", function);
- }
-
- /**
- * The color of the icon. This can only be used with sdf icons.
- *
- * @param value a int color value
- * @return property wrapper around String color
- */
- public static Property<String> iconColor(@ColorInt int value) {
- return new PaintProperty<>("icon-color", colorToRgbaString(value));
- }
-
- /**
- * The color of the icon. This can only be used with sdf icons.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> iconColor(String value) {
- return new PaintProperty<>("icon-color", value);
- }
-
- /**
- * The color of the icon. This can only be used with sdf icons.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> iconColor(Function<String> function) {
- return new PaintProperty<>("icon-color", function);
- }
-
- /**
- * The color of the icon's halo. Icon halos can only be used with SDF icons.
- *
- * @param value a int color value
- * @return property wrapper around String color
- */
- public static Property<String> iconHaloColor(@ColorInt int value) {
- return new PaintProperty<>("icon-halo-color", colorToRgbaString(value));
- }
-
- /**
- * The color of the icon's halo. Icon halos can only be used with SDF icons.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> iconHaloColor(String value) {
- return new PaintProperty<>("icon-halo-color", value);
- }
-
- /**
- * The color of the icon's halo. Icon halos can only be used with SDF icons.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> iconHaloColor(Function<String> function) {
- return new PaintProperty<>("icon-halo-color", function);
- }
-
- /**
- * Distance of halo to the icon outline.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> iconHaloWidth(Float value) {
- return new PaintProperty<>("icon-halo-width", value);
- }
-
- /**
- * Distance of halo to the icon outline.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> iconHaloWidth(Function<Float> function) {
- return new PaintProperty<>("icon-halo-width", function);
- }
-
- /**
- * Fade out the halo towards the outside.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> iconHaloBlur(Float value) {
- return new PaintProperty<>("icon-halo-blur", value);
- }
-
- /**
- * Fade out the halo towards the outside.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> iconHaloBlur(Function<Float> function) {
- return new PaintProperty<>("icon-halo-blur", function);
- }
-
- /**
- * Distance that the icon's anchor is moved from its original placement. Positive values indicate right and down, while negative values indicate left and up.
- *
- * @param value a Float[] value
- * @return property wrapper around Float[]
- */
- public static Property<Float[]> iconTranslate(Float[] value) {
- return new PaintProperty<>("icon-translate", value);
- }
-
- /**
- * Distance that the icon's anchor is moved from its original placement. Positive values indicate right and down, while negative values indicate left and up.
- *
- * @param function a wrapper function for Float[]
- * @return property wrapper around a Float[] function
- */
- public static Property<Function<Float[]>> iconTranslate(Function<Float[]> function) {
- return new PaintProperty<>("icon-translate", function);
- }
-
- /**
- * Controls the translation reference point.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> iconTranslateAnchor(@Property.ICON_TRANSLATE_ANCHOR String value) {
- return new PaintProperty<>("icon-translate-anchor", value);
- }
-
- /**
- * Controls the translation reference point.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> iconTranslateAnchor(Function<String> function) {
- return new PaintProperty<>("icon-translate-anchor", function);
- }
-
- /**
- * The opacity at which the text will be drawn.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> textOpacity(Float value) {
- return new PaintProperty<>("text-opacity", value);
- }
-
- /**
- * The opacity at which the text will be drawn.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> textOpacity(Function<Float> function) {
- return new PaintProperty<>("text-opacity", function);
- }
-
- /**
- * The color with which the text will be drawn.
- *
- * @param value a int color value
- * @return property wrapper around String color
- */
- public static Property<String> textColor(@ColorInt int value) {
- return new PaintProperty<>("text-color", colorToRgbaString(value));
- }
-
- /**
- * The color with which the text will be drawn.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> textColor(String value) {
- return new PaintProperty<>("text-color", value);
- }
-
- /**
- * The color with which the text will be drawn.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> textColor(Function<String> function) {
- return new PaintProperty<>("text-color", function);
- }
-
- /**
- * The color of the text's halo, which helps it stand out from backgrounds.
- *
- * @param value a int color value
- * @return property wrapper around String color
- */
- public static Property<String> textHaloColor(@ColorInt int value) {
- return new PaintProperty<>("text-halo-color", colorToRgbaString(value));
- }
-
- /**
- * The color of the text's halo, which helps it stand out from backgrounds.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> textHaloColor(String value) {
- return new PaintProperty<>("text-halo-color", value);
- }
-
- /**
- * The color of the text's halo, which helps it stand out from backgrounds.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> textHaloColor(Function<String> function) {
- return new PaintProperty<>("text-halo-color", function);
- }
-
- /**
- * Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> textHaloWidth(Float value) {
- return new PaintProperty<>("text-halo-width", value);
- }
-
- /**
- * Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> textHaloWidth(Function<Float> function) {
- return new PaintProperty<>("text-halo-width", function);
- }
-
- /**
- * The halo's fadeout distance towards the outside.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> textHaloBlur(Float value) {
- return new PaintProperty<>("text-halo-blur", value);
- }
-
- /**
- * The halo's fadeout distance towards the outside.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> textHaloBlur(Function<Float> function) {
- return new PaintProperty<>("text-halo-blur", function);
- }
-
- /**
- * Distance that the text's anchor is moved from its original placement. Positive values indicate right and down, while negative values indicate left and up.
- *
- * @param value a Float[] value
- * @return property wrapper around Float[]
- */
- public static Property<Float[]> textTranslate(Float[] value) {
- return new PaintProperty<>("text-translate", value);
- }
-
- /**
- * Distance that the text's anchor is moved from its original placement. Positive values indicate right and down, while negative values indicate left and up.
- *
- * @param function a wrapper function for Float[]
- * @return property wrapper around a Float[] function
- */
- public static Property<Function<Float[]>> textTranslate(Function<Float[]> function) {
- return new PaintProperty<>("text-translate", function);
- }
-
- /**
- * Controls the translation reference point.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> textTranslateAnchor(@Property.TEXT_TRANSLATE_ANCHOR String value) {
- return new PaintProperty<>("text-translate-anchor", value);
- }
-
- /**
- * Controls the translation reference point.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> textTranslateAnchor(Function<String> function) {
- return new PaintProperty<>("text-translate-anchor", function);
- }
-
- /**
- * Circle radius.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> circleRadius(Float value) {
- return new PaintProperty<>("circle-radius", value);
- }
-
- /**
- * Circle radius.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> circleRadius(Function<Float> function) {
- return new PaintProperty<>("circle-radius", function);
- }
-
- /**
- * The fill color of the circle.
- *
- * @param value a int color value
- * @return property wrapper around String color
- */
- public static Property<String> circleColor(@ColorInt int value) {
- return new PaintProperty<>("circle-color", colorToRgbaString(value));
- }
-
- /**
- * The fill color of the circle.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> circleColor(String value) {
- return new PaintProperty<>("circle-color", value);
- }
-
- /**
- * The fill color of the circle.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> circleColor(Function<String> function) {
- return new PaintProperty<>("circle-color", function);
- }
-
- /**
- * Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> circleBlur(Float value) {
- return new PaintProperty<>("circle-blur", value);
- }
-
- /**
- * Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> circleBlur(Function<Float> function) {
- return new PaintProperty<>("circle-blur", function);
- }
-
- /**
- * The opacity at which the circle will be drawn.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> circleOpacity(Float value) {
- return new PaintProperty<>("circle-opacity", value);
- }
-
- /**
- * The opacity at which the circle will be drawn.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> circleOpacity(Function<Float> function) {
- return new PaintProperty<>("circle-opacity", function);
- }
-
- /**
- * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
- *
- * @param value a Float[] value
- * @return property wrapper around Float[]
- */
- public static Property<Float[]> circleTranslate(Float[] value) {
- return new PaintProperty<>("circle-translate", value);
- }
-
- /**
- * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
- *
- * @param function a wrapper function for Float[]
- * @return property wrapper around a Float[] function
- */
- public static Property<Function<Float[]>> circleTranslate(Function<Float[]> function) {
- return new PaintProperty<>("circle-translate", function);
- }
-
- /**
- * Controls the translation reference point.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> circleTranslateAnchor(@Property.CIRCLE_TRANSLATE_ANCHOR String value) {
- return new PaintProperty<>("circle-translate-anchor", value);
- }
-
- /**
- * Controls the translation reference point.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> circleTranslateAnchor(Function<String> function) {
- return new PaintProperty<>("circle-translate-anchor", function);
- }
-
- /**
- * Controls the scaling behavior of the circle when the map is pitched.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> circlePitchScale(@Property.CIRCLE_PITCH_SCALE String value) {
- return new PaintProperty<>("circle-pitch-scale", value);
- }
-
- /**
- * Controls the scaling behavior of the circle when the map is pitched.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> circlePitchScale(Function<String> function) {
- return new PaintProperty<>("circle-pitch-scale", function);
- }
-
- /**
- * The opacity at which the image will be drawn.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> rasterOpacity(Float value) {
- return new PaintProperty<>("raster-opacity", value);
- }
-
- /**
- * The opacity at which the image will be drawn.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> rasterOpacity(Function<Float> function) {
- return new PaintProperty<>("raster-opacity", function);
- }
-
- /**
- * Rotates hues around the color wheel.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> rasterHueRotate(Float value) {
- return new PaintProperty<>("raster-hue-rotate", value);
- }
-
- /**
- * Rotates hues around the color wheel.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> rasterHueRotate(Function<Float> function) {
- return new PaintProperty<>("raster-hue-rotate", function);
- }
-
- /**
- * Increase or reduce the brightness of the image. The value is the minimum brightness.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> rasterBrightnessMin(Float value) {
- return new PaintProperty<>("raster-brightness-min", value);
- }
-
- /**
- * Increase or reduce the brightness of the image. The value is the minimum brightness.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> rasterBrightnessMin(Function<Float> function) {
- return new PaintProperty<>("raster-brightness-min", function);
- }
-
- /**
- * Increase or reduce the brightness of the image. The value is the maximum brightness.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> rasterBrightnessMax(Float value) {
- return new PaintProperty<>("raster-brightness-max", value);
- }
-
- /**
- * Increase or reduce the brightness of the image. The value is the maximum brightness.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> rasterBrightnessMax(Function<Float> function) {
- return new PaintProperty<>("raster-brightness-max", function);
- }
-
- /**
- * Increase or reduce the saturation of the image.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> rasterSaturation(Float value) {
- return new PaintProperty<>("raster-saturation", value);
- }
-
- /**
- * Increase or reduce the saturation of the image.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> rasterSaturation(Function<Float> function) {
- return new PaintProperty<>("raster-saturation", function);
- }
-
- /**
- * Increase or reduce the contrast of the image.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> rasterContrast(Float value) {
- return new PaintProperty<>("raster-contrast", value);
- }
-
- /**
- * Increase or reduce the contrast of the image.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> rasterContrast(Function<Float> function) {
- return new PaintProperty<>("raster-contrast", function);
- }
-
- /**
- * Fade duration when a new tile is added.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> rasterFadeDuration(Float value) {
- return new PaintProperty<>("raster-fade-duration", value);
- }
-
- /**
- * Fade duration when a new tile is added.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> rasterFadeDuration(Function<Float> function) {
- return new PaintProperty<>("raster-fade-duration", function);
- }
-
- /**
- * The color with which the background will be drawn.
- *
- * @param value a int color value
- * @return property wrapper around String color
- */
- public static Property<String> backgroundColor(@ColorInt int value) {
- return new PaintProperty<>("background-color", colorToRgbaString(value));
- }
-
- /**
- * The color with which the background will be drawn.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> backgroundColor(String value) {
- return new PaintProperty<>("background-color", value);
- }
-
- /**
- * The color with which the background will be drawn.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> backgroundColor(Function<String> function) {
- return new PaintProperty<>("background-color", function);
- }
-
- /**
- * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> backgroundPattern(String value) {
- return new PaintProperty<>("background-pattern", value);
- }
-
- /**
- * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> backgroundPattern(Function<String> function) {
- return new PaintProperty<>("background-pattern", function);
- }
-
- /**
- * The opacity at which the background will be drawn.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> backgroundOpacity(Float value) {
- return new PaintProperty<>("background-opacity", value);
- }
-
- /**
- * The opacity at which the background will be drawn.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> backgroundOpacity(Function<Float> function) {
- return new PaintProperty<>("background-opacity", function);
- }
-
- /**
- * The display of line endings.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> lineCap(@Property.LINE_CAP String value) {
- return new LayoutProperty<>("line-cap", value);
- }
-
- /**
- * The display of line endings.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> lineCap(Function<String> function) {
- return new LayoutProperty<>("line-cap", function);
- }
-
- /**
- * The display of lines when joining.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> lineJoin(@Property.LINE_JOIN String value) {
- return new LayoutProperty<>("line-join", value);
- }
-
- /**
- * The display of lines when joining.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> lineJoin(Function<String> function) {
- return new LayoutProperty<>("line-join", function);
- }
-
- /**
- * Used to automatically convert miter joins to bevel joins for sharp angles.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> lineMiterLimit(Float value) {
- return new LayoutProperty<>("line-miter-limit", value);
- }
-
- /**
- * Used to automatically convert miter joins to bevel joins for sharp angles.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> lineMiterLimit(Function<Float> function) {
- return new LayoutProperty<>("line-miter-limit", function);
- }
-
- /**
- * Used to automatically convert round joins to miter joins for shallow angles.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> lineRoundLimit(Float value) {
- return new LayoutProperty<>("line-round-limit", value);
- }
-
- /**
- * Used to automatically convert round joins to miter joins for shallow angles.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> lineRoundLimit(Function<Float> function) {
- return new LayoutProperty<>("line-round-limit", function);
- }
-
- /**
- * Label placement relative to its geometry.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> symbolPlacement(@Property.SYMBOL_PLACEMENT String value) {
- return new LayoutProperty<>("symbol-placement", value);
- }
-
- /**
- * Label placement relative to its geometry.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> symbolPlacement(Function<String> function) {
- return new LayoutProperty<>("symbol-placement", function);
- }
-
- /**
- * Distance between two symbol anchors.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> symbolSpacing(Float value) {
- return new LayoutProperty<>("symbol-spacing", value);
- }
-
- /**
- * Distance between two symbol anchors.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> symbolSpacing(Function<Float> function) {
- return new LayoutProperty<>("symbol-spacing", function);
- }
-
- /**
- * If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer.
- *
- * @param value a Boolean value
- * @return property wrapper around Boolean
- */
- public static Property<Boolean> symbolAvoidEdges(Boolean value) {
- return new LayoutProperty<>("symbol-avoid-edges", value);
- }
-
- /**
- * If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer.
- *
- * @param function a wrapper function for Boolean
- * @return property wrapper around a Boolean function
- */
- public static Property<Function<Boolean>> symbolAvoidEdges(Function<Boolean> function) {
- return new LayoutProperty<>("symbol-avoid-edges", function);
- }
-
- /**
- * If true, the icon will be visible even if it collides with other previously drawn symbols.
- *
- * @param value a Boolean value
- * @return property wrapper around Boolean
- */
- public static Property<Boolean> iconAllowOverlap(Boolean value) {
- return new LayoutProperty<>("icon-allow-overlap", value);
- }
-
- /**
- * If true, the icon will be visible even if it collides with other previously drawn symbols.
- *
- * @param function a wrapper function for Boolean
- * @return property wrapper around a Boolean function
- */
- public static Property<Function<Boolean>> iconAllowOverlap(Function<Boolean> function) {
- return new LayoutProperty<>("icon-allow-overlap", function);
- }
-
- /**
- * If true, other symbols can be visible even if they collide with the icon.
- *
- * @param value a Boolean value
- * @return property wrapper around Boolean
- */
- public static Property<Boolean> iconIgnorePlacement(Boolean value) {
- return new LayoutProperty<>("icon-ignore-placement", value);
- }
-
- /**
- * If true, other symbols can be visible even if they collide with the icon.
- *
- * @param function a wrapper function for Boolean
- * @return property wrapper around a Boolean function
- */
- public static Property<Function<Boolean>> iconIgnorePlacement(Function<Boolean> function) {
- return new LayoutProperty<>("icon-ignore-placement", function);
- }
-
- /**
- * If true, text will display without their corresponding icons when the icon collides with other symbols and the text does not.
- *
- * @param value a Boolean value
- * @return property wrapper around Boolean
- */
- public static Property<Boolean> iconOptional(Boolean value) {
- return new LayoutProperty<>("icon-optional", value);
- }
-
- /**
- * If true, text will display without their corresponding icons when the icon collides with other symbols and the text does not.
- *
- * @param function a wrapper function for Boolean
- * @return property wrapper around a Boolean function
- */
- public static Property<Function<Boolean>> iconOptional(Function<Boolean> function) {
- return new LayoutProperty<>("icon-optional", function);
- }
-
- /**
- * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of icons.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> iconRotationAlignment(@Property.ICON_ROTATION_ALIGNMENT String value) {
- return new LayoutProperty<>("icon-rotation-alignment", value);
- }
-
- /**
- * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of icons.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> iconRotationAlignment(Function<String> function) {
- return new LayoutProperty<>("icon-rotation-alignment", function);
- }
-
- /**
- * Scale factor for icon. 1 is original size, 3 triples the size.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> iconSize(Float value) {
- return new LayoutProperty<>("icon-size", value);
- }
-
- /**
- * Scale factor for icon. 1 is original size, 3 triples the size.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> iconSize(Function<Float> function) {
- return new LayoutProperty<>("icon-size", function);
- }
-
- /**
- * Scales the icon to fit around the associated text.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> iconTextFit(@Property.ICON_TEXT_FIT String value) {
- return new LayoutProperty<>("icon-text-fit", value);
- }
-
- /**
- * Scales the icon to fit around the associated text.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> iconTextFit(Function<String> function) {
- return new LayoutProperty<>("icon-text-fit", function);
- }
-
- /**
- * Size of the additional area added to dimensions determined by {@link Property.ICON_TEXT_FIT}, in clockwise order: top, right, bottom, left.
- *
- * @param value a Float[] value
- * @return property wrapper around Float[]
- */
- public static Property<Float[]> iconTextFitPadding(Float[] value) {
- return new LayoutProperty<>("icon-text-fit-padding", value);
- }
-
- /**
- * Size of the additional area added to dimensions determined by {@link Property.ICON_TEXT_FIT}, in clockwise order: top, right, bottom, left.
- *
- * @param function a wrapper function for Float[]
- * @return property wrapper around a Float[] function
- */
- public static Property<Function<Float[]>> iconTextFitPadding(Function<Float[]> function) {
- return new LayoutProperty<>("icon-text-fit-padding", function);
- }
-
- /**
- * A string with {tokens} replaced, referencing the data property to pull from.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> iconImage(String value) {
- return new LayoutProperty<>("icon-image", value);
- }
-
- /**
- * A string with {tokens} replaced, referencing the data property to pull from.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> iconImage(Function<String> function) {
- return new LayoutProperty<>("icon-image", function);
- }
-
- /**
- * Rotates the icon clockwise.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> iconRotate(Float value) {
- return new LayoutProperty<>("icon-rotate", value);
- }
-
- /**
- * Rotates the icon clockwise.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> iconRotate(Function<Float> function) {
- return new LayoutProperty<>("icon-rotate", function);
- }
-
- /**
- * Size of the additional area around the icon bounding box used for detecting symbol collisions.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> iconPadding(Float value) {
- return new LayoutProperty<>("icon-padding", value);
- }
-
- /**
- * Size of the additional area around the icon bounding box used for detecting symbol collisions.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> iconPadding(Function<Float> function) {
- return new LayoutProperty<>("icon-padding", function);
- }
-
- /**
- * If true, the icon may be flipped to prevent it from being rendered upside-down.
- *
- * @param value a Boolean value
- * @return property wrapper around Boolean
- */
- public static Property<Boolean> iconKeepUpright(Boolean value) {
- return new LayoutProperty<>("icon-keep-upright", value);
- }
-
- /**
- * If true, the icon may be flipped to prevent it from being rendered upside-down.
- *
- * @param function a wrapper function for Boolean
- * @return property wrapper around a Boolean function
- */
- public static Property<Function<Boolean>> iconKeepUpright(Function<Boolean> function) {
- return new LayoutProperty<>("icon-keep-upright", function);
- }
-
- /**
- * Offset distance of icon from its anchor. Positive values indicate right and down, while negative values indicate left and up.
- *
- * @param value a Float[] value
- * @return property wrapper around Float[]
- */
- public static Property<Float[]> iconOffset(Float[] value) {
- return new LayoutProperty<>("icon-offset", value);
- }
-
- /**
- * Offset distance of icon from its anchor. Positive values indicate right and down, while negative values indicate left and up.
- *
- * @param function a wrapper function for Float[]
- * @return property wrapper around a Float[] function
- */
- public static Property<Function<Float[]>> iconOffset(Function<Float[]> function) {
- return new LayoutProperty<>("icon-offset", function);
- }
-
- /**
- * Orientation of text when map is pitched.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> textPitchAlignment(@Property.TEXT_PITCH_ALIGNMENT String value) {
- return new LayoutProperty<>("text-pitch-alignment", value);
- }
-
- /**
- * Orientation of text when map is pitched.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> textPitchAlignment(Function<String> function) {
- return new LayoutProperty<>("text-pitch-alignment", function);
- }
-
- /**
- * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of the individual glyphs forming the text.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> textRotationAlignment(@Property.TEXT_ROTATION_ALIGNMENT String value) {
- return new LayoutProperty<>("text-rotation-alignment", value);
- }
-
- /**
- * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of the individual glyphs forming the text.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> textRotationAlignment(Function<String> function) {
- return new LayoutProperty<>("text-rotation-alignment", function);
- }
-
- /**
- * Value to use for a text label. Feature properties are specified using tokens like {field_name}.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> textField(String value) {
- return new LayoutProperty<>("text-field", value);
- }
-
- /**
- * Value to use for a text label. Feature properties are specified using tokens like {field_name}.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> textField(Function<String> function) {
- return new LayoutProperty<>("text-field", function);
- }
-
- /**
- * Font stack to use for displaying text.
- *
- * @param value a String[] value
- * @return property wrapper around String[]
- */
- public static Property<String[]> textFont(String[] value) {
- return new LayoutProperty<>("text-font", value);
- }
-
- /**
- * Font stack to use for displaying text.
- *
- * @param function a wrapper function for String[]
- * @return property wrapper around a String[] function
- */
- public static Property<Function<String[]>> textFont(Function<String[]> function) {
- return new LayoutProperty<>("text-font", function);
- }
-
- /**
- * Font size.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> textSize(Float value) {
- return new LayoutProperty<>("text-size", value);
- }
-
- /**
- * Font size.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> textSize(Function<Float> function) {
- return new LayoutProperty<>("text-size", function);
- }
-
- /**
- * The maximum line width for text wrapping.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> textMaxWidth(Float value) {
- return new LayoutProperty<>("text-max-width", value);
- }
-
- /**
- * The maximum line width for text wrapping.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> textMaxWidth(Function<Float> function) {
- return new LayoutProperty<>("text-max-width", function);
- }
-
- /**
- * Text leading value for multi-line text.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> textLineHeight(Float value) {
- return new LayoutProperty<>("text-line-height", value);
- }
-
- /**
- * Text leading value for multi-line text.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> textLineHeight(Function<Float> function) {
- return new LayoutProperty<>("text-line-height", function);
- }
-
- /**
- * Text tracking amount.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> textLetterSpacing(Float value) {
- return new LayoutProperty<>("text-letter-spacing", value);
- }
-
- /**
- * Text tracking amount.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> textLetterSpacing(Function<Float> function) {
- return new LayoutProperty<>("text-letter-spacing", function);
- }
-
- /**
- * Text justification options.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> textJustify(@Property.TEXT_JUSTIFY String value) {
- return new LayoutProperty<>("text-justify", value);
- }
-
- /**
- * Text justification options.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> textJustify(Function<String> function) {
- return new LayoutProperty<>("text-justify", function);
- }
-
- /**
- * Part of the text placed closest to the anchor.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> textAnchor(@Property.TEXT_ANCHOR String value) {
- return new LayoutProperty<>("text-anchor", value);
- }
-
- /**
- * Part of the text placed closest to the anchor.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> textAnchor(Function<String> function) {
- return new LayoutProperty<>("text-anchor", function);
- }
-
- /**
- * Maximum angle change between adjacent characters.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> textMaxAngle(Float value) {
- return new LayoutProperty<>("text-max-angle", value);
- }
-
- /**
- * Maximum angle change between adjacent characters.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> textMaxAngle(Function<Float> function) {
- return new LayoutProperty<>("text-max-angle", function);
- }
-
- /**
- * Rotates the text clockwise.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> textRotate(Float value) {
- return new LayoutProperty<>("text-rotate", value);
- }
-
- /**
- * Rotates the text clockwise.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> textRotate(Function<Float> function) {
- return new LayoutProperty<>("text-rotate", function);
- }
-
- /**
- * Size of the additional area around the text bounding box used for detecting symbol collisions.
- *
- * @param value a Float value
- * @return property wrapper around Float
- */
- public static Property<Float> textPadding(Float value) {
- return new LayoutProperty<>("text-padding", value);
- }
-
- /**
- * Size of the additional area around the text bounding box used for detecting symbol collisions.
- *
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static Property<Function<Float>> textPadding(Function<Float> function) {
- return new LayoutProperty<>("text-padding", function);
- }
-
- /**
- * If true, the text may be flipped vertically to prevent it from being rendered upside-down.
- *
- * @param value a Boolean value
- * @return property wrapper around Boolean
- */
- public static Property<Boolean> textKeepUpright(Boolean value) {
- return new LayoutProperty<>("text-keep-upright", value);
- }
-
- /**
- * If true, the text may be flipped vertically to prevent it from being rendered upside-down.
- *
- * @param function a wrapper function for Boolean
- * @return property wrapper around a Boolean function
- */
- public static Property<Function<Boolean>> textKeepUpright(Function<Boolean> function) {
- return new LayoutProperty<>("text-keep-upright", function);
- }
-
- /**
- * Specifies how to capitalize text, similar to the CSS {@link PropertyFactory#textTransform} property.
- *
- * @param value a String value
- * @return property wrapper around String
- */
- public static Property<String> textTransform(@Property.TEXT_TRANSFORM String value) {
- return new LayoutProperty<>("text-transform", value);
- }
-
- /**
- * Specifies how to capitalize text, similar to the CSS {@link PropertyFactory#textTransform} property.
- *
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static Property<Function<String>> textTransform(Function<String> function) {
- return new LayoutProperty<>("text-transform", function);
- }
-
- /**
- * Offset distance of text from its anchor. Positive values indicate right and down, while negative values indicate left and up.
- *
- * @param value a Float[] value
- * @return property wrapper around Float[]
- */
- public static Property<Float[]> textOffset(Float[] value) {
- return new LayoutProperty<>("text-offset", value);
- }
-
- /**
- * Offset distance of text from its anchor. Positive values indicate right and down, while negative values indicate left and up.
- *
- * @param function a wrapper function for Float[]
- * @return property wrapper around a Float[] function
- */
- public static Property<Function<Float[]>> textOffset(Function<Float[]> function) {
- return new LayoutProperty<>("text-offset", function);
- }
-
- /**
- * If true, the text will be visible even if it collides with other previously drawn symbols.
- *
- * @param value a Boolean value
- * @return property wrapper around Boolean
- */
- public static Property<Boolean> textAllowOverlap(Boolean value) {
- return new LayoutProperty<>("text-allow-overlap", value);
- }
-
- /**
- * If true, the text will be visible even if it collides with other previously drawn symbols.
- *
- * @param function a wrapper function for Boolean
- * @return property wrapper around a Boolean function
- */
- public static Property<Function<Boolean>> textAllowOverlap(Function<Boolean> function) {
- return new LayoutProperty<>("text-allow-overlap", function);
- }
-
- /**
- * If true, other symbols can be visible even if they collide with the text.
- *
- * @param value a Boolean value
- * @return property wrapper around Boolean
- */
- public static Property<Boolean> textIgnorePlacement(Boolean value) {
- return new LayoutProperty<>("text-ignore-placement", value);
- }
-
- /**
- * If true, other symbols can be visible even if they collide with the text.
- *
- * @param function a wrapper function for Boolean
- * @return property wrapper around a Boolean function
- */
- public static Property<Function<Boolean>> textIgnorePlacement(Function<Boolean> function) {
- return new LayoutProperty<>("text-ignore-placement", function);
- }
-
- /**
- * If true, icons will display without their corresponding text when the text collides with other symbols and the icon does not.
- *
- * @param value a Boolean value
- * @return property wrapper around Boolean
- */
- public static Property<Boolean> textOptional(Boolean value) {
- return new LayoutProperty<>("text-optional", value);
- }
-
- /**
- * If true, icons will display without their corresponding text when the text collides with other symbols and the icon does not.
- *
- * @param function a wrapper function for Boolean
- * @return property wrapper around a Boolean function
- */
- public static Property<Function<Boolean>> textOptional(Function<Boolean> function) {
- return new LayoutProperty<>("text-optional", function);
- }
-
- @SuppressLint("DefaultLocale")
- static String colorToRgbaString(@ColorInt int value) {
- return String.format("rgba(%d, %d, %d, %d)", (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF, (value >> 24) & 0xFF);
- }
+ /**
+ * Set the property visibility.
+ *
+ * @param value the visibility value
+ * @return property wrapper around visibility
+ */
+ public static Property<String> visibility(@Property.VISIBILITY String value) {
+ return new LayoutProperty<>("visibility", value);
+ }
+
+ /**
+ * Set the property visibility.
+ *
+ * @param function the visibility function
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> visibility(Function<String> function) {
+ return new LayoutProperty<>("visibility", function);
+ }
+
+ /**
+ * Whether or not the fill should be antialiased.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static Property<Boolean> fillAntialias(Boolean value) {
+ return new PaintProperty<>("fill-antialias", value);
+ }
+
+ /**
+ * Whether or not the fill should be antialiased.
+ *
+ * @param function a wrapper function for Boolean
+ * @return property wrapper around a Boolean function
+ */
+ public static Property<Function<Boolean>> fillAntialias(Function<Boolean> function) {
+ return new PaintProperty<>("fill-antialias", function);
+ }
+
+ /**
+ * The opacity of the entire fill layer. In contrast to the {@link PropertyFactory#fillColor}, this value will also
+ * affect the 1px stroke around the fill, if the stroke is used.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> fillOpacity(Float value) {
+ return new PaintProperty<>("fill-opacity", value);
+ }
+
+ /**
+ * The opacity of the entire fill layer. In contrast to the {@link PropertyFactory#fillColor}, this value will also
+ * affect the 1px stroke around the fill, if the stroke is used.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> fillOpacity(Function<Float> function) {
+ return new PaintProperty<>("fill-opacity", function);
+ }
+
+ /**
+ * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the
+ * color's opacity will not affect the opacity of the 1px stroke, if it is used.
+ *
+ * @param value a int color value
+ * @return property wrapper around String color
+ */
+ public static Property<String> fillColor(@ColorInt int value) {
+ return new PaintProperty<>("fill-color", colorToRgbaString(value));
+ }
+
+ /**
+ * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the
+ * color's opacity will not affect the opacity of the 1px stroke, if it is used.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> fillColor(String value) {
+ return new PaintProperty<>("fill-color", value);
+ }
+
+ /**
+ * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the
+ * color's opacity will not affect the opacity of the 1px stroke, if it is used.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> fillColor(Function<String> function) {
+ return new PaintProperty<>("fill-color", function);
+ }
+
+ /**
+ * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified.
+ *
+ * @param value a int color value
+ * @return property wrapper around String color
+ */
+ public static Property<String> fillOutlineColor(@ColorInt int value) {
+ return new PaintProperty<>("fill-outline-color", colorToRgbaString(value));
+ }
+
+ /**
+ * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> fillOutlineColor(String value) {
+ return new PaintProperty<>("fill-outline-color", value);
+ }
+
+ /**
+ * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> fillOutlineColor(Function<String> function) {
+ return new PaintProperty<>("fill-outline-color", function);
+ }
+
+ /**
+ * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
+ *
+ * @param value a Float[] value
+ * @return property wrapper around Float[]
+ */
+ public static Property<Float[]> fillTranslate(Float[] value) {
+ return new PaintProperty<>("fill-translate", value);
+ }
+
+ /**
+ * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
+ *
+ * @param function a wrapper function for Float[]
+ * @return property wrapper around a Float[] function
+ */
+ public static Property<Function<Float[]>> fillTranslate(Function<Float[]> function) {
+ return new PaintProperty<>("fill-translate", function);
+ }
+
+ /**
+ * Controls the translation reference point.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> fillTranslateAnchor(@Property.FILL_TRANSLATE_ANCHOR String value) {
+ return new PaintProperty<>("fill-translate-anchor", value);
+ }
+
+ /**
+ * Controls the translation reference point.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> fillTranslateAnchor(Function<String> function) {
+ return new PaintProperty<>("fill-translate-anchor", function);
+ }
+
+ /**
+ * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a
+ * factor of two (2, 4, 8, ..., 512).
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> fillPattern(String value) {
+ return new PaintProperty<>("fill-pattern", value);
+ }
+
+ /**
+ * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a
+ * factor of two (2, 4, 8, ..., 512).
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> fillPattern(Function<String> function) {
+ return new PaintProperty<>("fill-pattern", function);
+ }
+
+ /**
+ * The opacity at which the line will be drawn.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> lineOpacity(Float value) {
+ return new PaintProperty<>("line-opacity", value);
+ }
+
+ /**
+ * The opacity at which the line will be drawn.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> lineOpacity(Function<Float> function) {
+ return new PaintProperty<>("line-opacity", function);
+ }
+
+ /**
+ * The color with which the line will be drawn.
+ *
+ * @param value a int color value
+ * @return property wrapper around String color
+ */
+ public static Property<String> lineColor(@ColorInt int value) {
+ return new PaintProperty<>("line-color", colorToRgbaString(value));
+ }
+
+ /**
+ * The color with which the line will be drawn.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> lineColor(String value) {
+ return new PaintProperty<>("line-color", value);
+ }
+
+ /**
+ * The color with which the line will be drawn.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> lineColor(Function<String> function) {
+ return new PaintProperty<>("line-color", function);
+ }
+
+ /**
+ * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
+ *
+ * @param value a Float[] value
+ * @return property wrapper around Float[]
+ */
+ public static Property<Float[]> lineTranslate(Float[] value) {
+ return new PaintProperty<>("line-translate", value);
+ }
+
+ /**
+ * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
+ *
+ * @param function a wrapper function for Float[]
+ * @return property wrapper around a Float[] function
+ */
+ public static Property<Function<Float[]>> lineTranslate(Function<Float[]> function) {
+ return new PaintProperty<>("line-translate", function);
+ }
+
+ /**
+ * Controls the translation reference point.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> lineTranslateAnchor(@Property.LINE_TRANSLATE_ANCHOR String value) {
+ return new PaintProperty<>("line-translate-anchor", value);
+ }
+
+ /**
+ * Controls the translation reference point.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> lineTranslateAnchor(Function<String> function) {
+ return new PaintProperty<>("line-translate-anchor", function);
+ }
+
+ /**
+ * Stroke thickness.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> lineWidth(Float value) {
+ return new PaintProperty<>("line-width", value);
+ }
+
+ /**
+ * Stroke thickness.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> lineWidth(Function<Float> function) {
+ return new PaintProperty<>("line-width", function);
+ }
+
+ /**
+ * Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> lineGapWidth(Float value) {
+ return new PaintProperty<>("line-gap-width", value);
+ }
+
+ /**
+ * Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> lineGapWidth(Function<Float> function) {
+ return new PaintProperty<>("line-gap-width", function);
+ }
+
+ /**
+ * The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction
+ * of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a
+ * negative value results in an outset.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> lineOffset(Float value) {
+ return new PaintProperty<>("line-offset", value);
+ }
+
+ /**
+ * The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction
+ * of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a
+ * negative value results in an outset.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> lineOffset(Function<Float> function) {
+ return new PaintProperty<>("line-offset", function);
+ }
+
+ /**
+ * Blur applied to the line, in pixels.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> lineBlur(Float value) {
+ return new PaintProperty<>("line-blur", value);
+ }
+
+ /**
+ * Blur applied to the line, in pixels.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> lineBlur(Function<Float> function) {
+ return new PaintProperty<>("line-blur", function);
+ }
+
+ /**
+ * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled
+ * by the line width. To convert a dash length to pixels, multiply the length by the current line width.
+ *
+ * @param value a Float[] value
+ * @return property wrapper around Float[]
+ */
+ public static Property<Float[]> lineDasharray(Float[] value) {
+ return new PaintProperty<>("line-dasharray", value);
+ }
+
+ /**
+ * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled
+ * by the line width. To convert a dash length to pixels, multiply the length by the current line width.
+ *
+ * @param function a wrapper function for Float[]
+ * @return property wrapper around a Float[] function
+ */
+ public static Property<Function<Float[]>> lineDasharray(Function<Float[]> function) {
+ return new PaintProperty<>("line-dasharray", function);
+ }
+
+ /**
+ * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two
+ * (2, 4, 8, ..., 512).
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> linePattern(String value) {
+ return new PaintProperty<>("line-pattern", value);
+ }
+
+ /**
+ * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two
+ * (2, 4, 8, ..., 512).
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> linePattern(Function<String> function) {
+ return new PaintProperty<>("line-pattern", function);
+ }
+
+ /**
+ * The opacity at which the icon will be drawn.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> iconOpacity(Float value) {
+ return new PaintProperty<>("icon-opacity", value);
+ }
+
+ /**
+ * The opacity at which the icon will be drawn.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> iconOpacity(Function<Float> function) {
+ return new PaintProperty<>("icon-opacity", function);
+ }
+
+ /**
+ * The color of the icon. This can only be used with sdf icons.
+ *
+ * @param value a int color value
+ * @return property wrapper around String color
+ */
+ public static Property<String> iconColor(@ColorInt int value) {
+ return new PaintProperty<>("icon-color", colorToRgbaString(value));
+ }
+
+ /**
+ * The color of the icon. This can only be used with sdf icons.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> iconColor(String value) {
+ return new PaintProperty<>("icon-color", value);
+ }
+
+ /**
+ * The color of the icon. This can only be used with sdf icons.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> iconColor(Function<String> function) {
+ return new PaintProperty<>("icon-color", function);
+ }
+
+ /**
+ * The color of the icon's halo. Icon halos can only be used with SDF icons.
+ *
+ * @param value a int color value
+ * @return property wrapper around String color
+ */
+ public static Property<String> iconHaloColor(@ColorInt int value) {
+ return new PaintProperty<>("icon-halo-color", colorToRgbaString(value));
+ }
+
+ /**
+ * The color of the icon's halo. Icon halos can only be used with SDF icons.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> iconHaloColor(String value) {
+ return new PaintProperty<>("icon-halo-color", value);
+ }
+
+ /**
+ * The color of the icon's halo. Icon halos can only be used with SDF icons.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> iconHaloColor(Function<String> function) {
+ return new PaintProperty<>("icon-halo-color", function);
+ }
+
+ /**
+ * Distance of halo to the icon outline.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> iconHaloWidth(Float value) {
+ return new PaintProperty<>("icon-halo-width", value);
+ }
+
+ /**
+ * Distance of halo to the icon outline.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> iconHaloWidth(Function<Float> function) {
+ return new PaintProperty<>("icon-halo-width", function);
+ }
+
+ /**
+ * Fade out the halo towards the outside.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> iconHaloBlur(Float value) {
+ return new PaintProperty<>("icon-halo-blur", value);
+ }
+
+ /**
+ * Fade out the halo towards the outside.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> iconHaloBlur(Function<Float> function) {
+ return new PaintProperty<>("icon-halo-blur", function);
+ }
+
+ /**
+ * Distance that the icon's anchor is moved from its original placement. Positive values indicate right and down,
+ * while negative values indicate left and up.
+ *
+ * @param value a Float[] value
+ * @return property wrapper around Float[]
+ */
+ public static Property<Float[]> iconTranslate(Float[] value) {
+ return new PaintProperty<>("icon-translate", value);
+ }
+
+ /**
+ * Distance that the icon's anchor is moved from its original placement. Positive values indicate right and down,
+ * while negative values indicate left and up.
+ *
+ * @param function a wrapper function for Float[]
+ * @return property wrapper around a Float[] function
+ */
+ public static Property<Function<Float[]>> iconTranslate(Function<Float[]> function) {
+ return new PaintProperty<>("icon-translate", function);
+ }
+
+ /**
+ * Controls the translation reference point.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> iconTranslateAnchor(@Property.ICON_TRANSLATE_ANCHOR String value) {
+ return new PaintProperty<>("icon-translate-anchor", value);
+ }
+
+ /**
+ * Controls the translation reference point.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> iconTranslateAnchor(Function<String> function) {
+ return new PaintProperty<>("icon-translate-anchor", function);
+ }
+
+ /**
+ * The opacity at which the text will be drawn.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> textOpacity(Float value) {
+ return new PaintProperty<>("text-opacity", value);
+ }
+
+ /**
+ * The opacity at which the text will be drawn.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> textOpacity(Function<Float> function) {
+ return new PaintProperty<>("text-opacity", function);
+ }
+
+ /**
+ * The color with which the text will be drawn.
+ *
+ * @param value a int color value
+ * @return property wrapper around String color
+ */
+ public static Property<String> textColor(@ColorInt int value) {
+ return new PaintProperty<>("text-color", colorToRgbaString(value));
+ }
+
+ /**
+ * The color with which the text will be drawn.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> textColor(String value) {
+ return new PaintProperty<>("text-color", value);
+ }
+
+ /**
+ * The color with which the text will be drawn.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> textColor(Function<String> function) {
+ return new PaintProperty<>("text-color", function);
+ }
+
+ /**
+ * The color of the text's halo, which helps it stand out from backgrounds.
+ *
+ * @param value a int color value
+ * @return property wrapper around String color
+ */
+ public static Property<String> textHaloColor(@ColorInt int value) {
+ return new PaintProperty<>("text-halo-color", colorToRgbaString(value));
+ }
+
+ /**
+ * The color of the text's halo, which helps it stand out from backgrounds.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> textHaloColor(String value) {
+ return new PaintProperty<>("text-halo-color", value);
+ }
+
+ /**
+ * The color of the text's halo, which helps it stand out from backgrounds.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> textHaloColor(Function<String> function) {
+ return new PaintProperty<>("text-halo-color", function);
+ }
+
+ /**
+ * Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> textHaloWidth(Float value) {
+ return new PaintProperty<>("text-halo-width", value);
+ }
+
+ /**
+ * Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> textHaloWidth(Function<Float> function) {
+ return new PaintProperty<>("text-halo-width", function);
+ }
+
+ /**
+ * The halo's fadeout distance towards the outside.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> textHaloBlur(Float value) {
+ return new PaintProperty<>("text-halo-blur", value);
+ }
+
+ /**
+ * The halo's fadeout distance towards the outside.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> textHaloBlur(Function<Float> function) {
+ return new PaintProperty<>("text-halo-blur", function);
+ }
+
+ /**
+ * Distance that the text's anchor is moved from its original placement. Positive values indicate right and down,
+ * while negative values indicate left and up.
+ *
+ * @param value a Float[] value
+ * @return property wrapper around Float[]
+ */
+ public static Property<Float[]> textTranslate(Float[] value) {
+ return new PaintProperty<>("text-translate", value);
+ }
+
+ /**
+ * Distance that the text's anchor is moved from its original placement. Positive values indicate right and down,
+ * while negative values indicate left and up.
+ *
+ * @param function a wrapper function for Float[]
+ * @return property wrapper around a Float[] function
+ */
+ public static Property<Function<Float[]>> textTranslate(Function<Float[]> function) {
+ return new PaintProperty<>("text-translate", function);
+ }
+
+ /**
+ * Controls the translation reference point.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> textTranslateAnchor(@Property.TEXT_TRANSLATE_ANCHOR String value) {
+ return new PaintProperty<>("text-translate-anchor", value);
+ }
+
+ /**
+ * Controls the translation reference point.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> textTranslateAnchor(Function<String> function) {
+ return new PaintProperty<>("text-translate-anchor", function);
+ }
+
+ /**
+ * Circle radius.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> circleRadius(Float value) {
+ return new PaintProperty<>("circle-radius", value);
+ }
+
+ /**
+ * Circle radius.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> circleRadius(Function<Float> function) {
+ return new PaintProperty<>("circle-radius", function);
+ }
+
+ /**
+ * The fill color of the circle.
+ *
+ * @param value a int color value
+ * @return property wrapper around String color
+ */
+ public static Property<String> circleColor(@ColorInt int value) {
+ return new PaintProperty<>("circle-color", colorToRgbaString(value));
+ }
+
+ /**
+ * The fill color of the circle.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> circleColor(String value) {
+ return new PaintProperty<>("circle-color", value);
+ }
+
+ /**
+ * The fill color of the circle.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> circleColor(Function<String> function) {
+ return new PaintProperty<>("circle-color", function);
+ }
+
+ /**
+ * Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> circleBlur(Float value) {
+ return new PaintProperty<>("circle-blur", value);
+ }
+
+ /**
+ * Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> circleBlur(Function<Float> function) {
+ return new PaintProperty<>("circle-blur", function);
+ }
+
+ /**
+ * The opacity at which the circle will be drawn.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> circleOpacity(Float value) {
+ return new PaintProperty<>("circle-opacity", value);
+ }
+
+ /**
+ * The opacity at which the circle will be drawn.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> circleOpacity(Function<Float> function) {
+ return new PaintProperty<>("circle-opacity", function);
+ }
+
+ /**
+ * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
+ *
+ * @param value a Float[] value
+ * @return property wrapper around Float[]
+ */
+ public static Property<Float[]> circleTranslate(Float[] value) {
+ return new PaintProperty<>("circle-translate", value);
+ }
+
+ /**
+ * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
+ *
+ * @param function a wrapper function for Float[]
+ * @return property wrapper around a Float[] function
+ */
+ public static Property<Function<Float[]>> circleTranslate(Function<Float[]> function) {
+ return new PaintProperty<>("circle-translate", function);
+ }
+
+ /**
+ * Controls the translation reference point.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> circleTranslateAnchor(@Property.CIRCLE_TRANSLATE_ANCHOR String value) {
+ return new PaintProperty<>("circle-translate-anchor", value);
+ }
+
+ /**
+ * Controls the translation reference point.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> circleTranslateAnchor(Function<String> function) {
+ return new PaintProperty<>("circle-translate-anchor", function);
+ }
+
+ /**
+ * Controls the scaling behavior of the circle when the map is pitched.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> circlePitchScale(@Property.CIRCLE_PITCH_SCALE String value) {
+ return new PaintProperty<>("circle-pitch-scale", value);
+ }
+
+ /**
+ * Controls the scaling behavior of the circle when the map is pitched.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> circlePitchScale(Function<String> function) {
+ return new PaintProperty<>("circle-pitch-scale", function);
+ }
+
+ /**
+ * The width of the circle's stroke. Strokes are placed outside of the "circle-radius".
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> circleStrokeWidth(Float value) {
+ return new PaintProperty<>("circle-stroke-width", value);
+ }
+
+ /**
+ * The width of the circle's stroke. Strokes are placed outside of the "circle-radius".
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> circleStrokeWidth(Function<Float> function) {
+ return new PaintProperty<>("circle-stroke-width", function);
+ }
+
+ /**
+ * The stroke color of the circle.
+ *
+ * @param value a int color value
+ * @return property wrapper around String color
+ */
+ public static Property<String> circleStrokeColor(@ColorInt int value) {
+ return new PaintProperty<>("circle-stroke-color", colorToRgbaString(value));
+ }
+
+ /**
+ * The stroke color of the circle.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> circleStrokeColor(String value) {
+ return new PaintProperty<>("circle-stroke-color", value);
+ }
+
+ /**
+ * The stroke color of the circle.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> circleStrokeColor(Function<String> function) {
+ return new PaintProperty<>("circle-stroke-color", function);
+ }
+
+ /**
+ * The opacity of the circle's stroke.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> circleStrokeOpacity(Float value) {
+ return new PaintProperty<>("circle-stroke-opacity", value);
+ }
+
+ /**
+ * The opacity of the circle's stroke.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> circleStrokeOpacity(Function<Float> function) {
+ return new PaintProperty<>("circle-stroke-opacity", function);
+ }
+
+ /**
+ * The opacity at which the image will be drawn.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> rasterOpacity(Float value) {
+ return new PaintProperty<>("raster-opacity", value);
+ }
+
+ /**
+ * The opacity at which the image will be drawn.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> rasterOpacity(Function<Float> function) {
+ return new PaintProperty<>("raster-opacity", function);
+ }
+
+ /**
+ * Rotates hues around the color wheel.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> rasterHueRotate(Float value) {
+ return new PaintProperty<>("raster-hue-rotate", value);
+ }
+
+ /**
+ * Rotates hues around the color wheel.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> rasterHueRotate(Function<Float> function) {
+ return new PaintProperty<>("raster-hue-rotate", function);
+ }
+
+ /**
+ * Increase or reduce the brightness of the image. The value is the minimum brightness.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> rasterBrightnessMin(Float value) {
+ return new PaintProperty<>("raster-brightness-min", value);
+ }
+
+ /**
+ * Increase or reduce the brightness of the image. The value is the minimum brightness.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> rasterBrightnessMin(Function<Float> function) {
+ return new PaintProperty<>("raster-brightness-min", function);
+ }
+
+ /**
+ * Increase or reduce the brightness of the image. The value is the maximum brightness.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> rasterBrightnessMax(Float value) {
+ return new PaintProperty<>("raster-brightness-max", value);
+ }
+
+ /**
+ * Increase or reduce the brightness of the image. The value is the maximum brightness.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> rasterBrightnessMax(Function<Float> function) {
+ return new PaintProperty<>("raster-brightness-max", function);
+ }
+
+ /**
+ * Increase or reduce the saturation of the image.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> rasterSaturation(Float value) {
+ return new PaintProperty<>("raster-saturation", value);
+ }
+
+ /**
+ * Increase or reduce the saturation of the image.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> rasterSaturation(Function<Float> function) {
+ return new PaintProperty<>("raster-saturation", function);
+ }
+
+ /**
+ * Increase or reduce the contrast of the image.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> rasterContrast(Float value) {
+ return new PaintProperty<>("raster-contrast", value);
+ }
+
+ /**
+ * Increase or reduce the contrast of the image.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> rasterContrast(Function<Float> function) {
+ return new PaintProperty<>("raster-contrast", function);
+ }
+
+ /**
+ * Fade duration when a new tile is added.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> rasterFadeDuration(Float value) {
+ return new PaintProperty<>("raster-fade-duration", value);
+ }
+
+ /**
+ * Fade duration when a new tile is added.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> rasterFadeDuration(Function<Float> function) {
+ return new PaintProperty<>("raster-fade-duration", function);
+ }
+
+ /**
+ * The color with which the background will be drawn.
+ *
+ * @param value a int color value
+ * @return property wrapper around String color
+ */
+ public static Property<String> backgroundColor(@ColorInt int value) {
+ return new PaintProperty<>("background-color", colorToRgbaString(value));
+ }
+
+ /**
+ * The color with which the background will be drawn.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> backgroundColor(String value) {
+ return new PaintProperty<>("background-color", value);
+ }
+
+ /**
+ * The color with which the background will be drawn.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> backgroundColor(Function<String> function) {
+ return new PaintProperty<>("background-color", function);
+ }
+
+ /**
+ * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must
+ * be a factor of two (2, 4, 8, ..., 512).
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> backgroundPattern(String value) {
+ return new PaintProperty<>("background-pattern", value);
+ }
+
+ /**
+ * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must
+ * be a factor of two (2, 4, 8, ..., 512).
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> backgroundPattern(Function<String> function) {
+ return new PaintProperty<>("background-pattern", function);
+ }
+
+ /**
+ * The opacity at which the background will be drawn.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> backgroundOpacity(Float value) {
+ return new PaintProperty<>("background-opacity", value);
+ }
+
+ /**
+ * The opacity at which the background will be drawn.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> backgroundOpacity(Function<Float> function) {
+ return new PaintProperty<>("background-opacity", function);
+ }
+
+ /**
+ * The display of line endings.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> lineCap(@Property.LINE_CAP String value) {
+ return new LayoutProperty<>("line-cap", value);
+ }
+
+ /**
+ * The display of line endings.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> lineCap(Function<String> function) {
+ return new LayoutProperty<>("line-cap", function);
+ }
+
+ /**
+ * The display of lines when joining.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> lineJoin(@Property.LINE_JOIN String value) {
+ return new LayoutProperty<>("line-join", value);
+ }
+
+ /**
+ * The display of lines when joining.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> lineJoin(Function<String> function) {
+ return new LayoutProperty<>("line-join", function);
+ }
+
+ /**
+ * Used to automatically convert miter joins to bevel joins for sharp angles.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> lineMiterLimit(Float value) {
+ return new LayoutProperty<>("line-miter-limit", value);
+ }
+
+ /**
+ * Used to automatically convert miter joins to bevel joins for sharp angles.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> lineMiterLimit(Function<Float> function) {
+ return new LayoutProperty<>("line-miter-limit", function);
+ }
+
+ /**
+ * Used to automatically convert round joins to miter joins for shallow angles.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> lineRoundLimit(Float value) {
+ return new LayoutProperty<>("line-round-limit", value);
+ }
+
+ /**
+ * Used to automatically convert round joins to miter joins for shallow angles.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> lineRoundLimit(Function<Float> function) {
+ return new LayoutProperty<>("line-round-limit", function);
+ }
+
+ /**
+ * Label placement relative to its geometry.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> symbolPlacement(@Property.SYMBOL_PLACEMENT String value) {
+ return new LayoutProperty<>("symbol-placement", value);
+ }
+
+ /**
+ * Label placement relative to its geometry.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> symbolPlacement(Function<String> function) {
+ return new LayoutProperty<>("symbol-placement", function);
+ }
+
+ /**
+ * Distance between two symbol anchors.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> symbolSpacing(Float value) {
+ return new LayoutProperty<>("symbol-spacing", value);
+ }
+
+ /**
+ * Distance between two symbol anchors.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> symbolSpacing(Function<Float> function) {
+ return new LayoutProperty<>("symbol-spacing", function);
+ }
+
+ /**
+ * If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have
+ * enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line
+ * symbol layer.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static Property<Boolean> symbolAvoidEdges(Boolean value) {
+ return new LayoutProperty<>("symbol-avoid-edges", value);
+ }
+
+ /**
+ * If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have
+ * enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line
+ * symbol layer.
+ *
+ * @param function a wrapper function for Boolean
+ * @return property wrapper around a Boolean function
+ */
+ public static Property<Function<Boolean>> symbolAvoidEdges(Function<Boolean> function) {
+ return new LayoutProperty<>("symbol-avoid-edges", function);
+ }
+
+ /**
+ * If true, the icon will be visible even if it collides with other previously drawn symbols.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static Property<Boolean> iconAllowOverlap(Boolean value) {
+ return new LayoutProperty<>("icon-allow-overlap", value);
+ }
+
+ /**
+ * If true, the icon will be visible even if it collides with other previously drawn symbols.
+ *
+ * @param function a wrapper function for Boolean
+ * @return property wrapper around a Boolean function
+ */
+ public static Property<Function<Boolean>> iconAllowOverlap(Function<Boolean> function) {
+ return new LayoutProperty<>("icon-allow-overlap", function);
+ }
+
+ /**
+ * If true, other symbols can be visible even if they collide with the icon.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static Property<Boolean> iconIgnorePlacement(Boolean value) {
+ return new LayoutProperty<>("icon-ignore-placement", value);
+ }
+
+ /**
+ * If true, other symbols can be visible even if they collide with the icon.
+ *
+ * @param function a wrapper function for Boolean
+ * @return property wrapper around a Boolean function
+ */
+ public static Property<Function<Boolean>> iconIgnorePlacement(Function<Boolean> function) {
+ return new LayoutProperty<>("icon-ignore-placement", function);
+ }
+
+ /**
+ * If true, text will display without their corresponding icons when the icon collides with other symbols and the
+ * text does not.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static Property<Boolean> iconOptional(Boolean value) {
+ return new LayoutProperty<>("icon-optional", value);
+ }
+
+ /**
+ * If true, text will display without their corresponding icons when the icon collides with other symbols and the
+ * text does not.
+ *
+ * @param function a wrapper function for Boolean
+ * @return property wrapper around a Boolean function
+ */
+ public static Property<Function<Boolean>> iconOptional(Function<Boolean> function) {
+ return new LayoutProperty<>("icon-optional", function);
+ }
+
+ /**
+ * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of icons.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> iconRotationAlignment(@Property.ICON_ROTATION_ALIGNMENT String value) {
+ return new LayoutProperty<>("icon-rotation-alignment", value);
+ }
+
+ /**
+ * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of icons.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> iconRotationAlignment(Function<String> function) {
+ return new LayoutProperty<>("icon-rotation-alignment", function);
+ }
+
+ /**
+ * Scale factor for icon. 1 is original size, 3 triples the size.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> iconSize(Float value) {
+ return new LayoutProperty<>("icon-size", value);
+ }
+
+ /**
+ * Scale factor for icon. 1 is original size, 3 triples the size.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> iconSize(Function<Float> function) {
+ return new LayoutProperty<>("icon-size", function);
+ }
+
+ /**
+ * Scales the icon to fit around the associated text.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> iconTextFit(@Property.ICON_TEXT_FIT String value) {
+ return new LayoutProperty<>("icon-text-fit", value);
+ }
+
+ /**
+ * Scales the icon to fit around the associated text.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> iconTextFit(Function<String> function) {
+ return new LayoutProperty<>("icon-text-fit", function);
+ }
+
+ /**
+ * Size of the additional area added to dimensions determined by {@link Property.ICON_TEXT_FIT}, in clockwise order:
+ * top, right, bottom, left.
+ *
+ * @param value a Float[] value
+ * @return property wrapper around Float[]
+ */
+ public static Property<Float[]> iconTextFitPadding(Float[] value) {
+ return new LayoutProperty<>("icon-text-fit-padding", value);
+ }
+
+ /**
+ * Size of the additional area added to dimensions determined by {@link Property.ICON_TEXT_FIT}, in clockwise order:
+ * top, right, bottom, left.
+ *
+ * @param function a wrapper function for Float[]
+ * @return property wrapper around a Float[] function
+ */
+ public static Property<Function<Float[]>> iconTextFitPadding(Function<Float[]> function) {
+ return new LayoutProperty<>("icon-text-fit-padding", function);
+ }
+
+ /**
+ * A string with {tokens} replaced, referencing the data property to pull from.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> iconImage(String value) {
+ return new LayoutProperty<>("icon-image", value);
+ }
+
+ /**
+ * A string with {tokens} replaced, referencing the data property to pull from.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> iconImage(Function<String> function) {
+ return new LayoutProperty<>("icon-image", function);
+ }
+
+ /**
+ * Rotates the icon clockwise.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> iconRotate(Float value) {
+ return new LayoutProperty<>("icon-rotate", value);
+ }
+
+ /**
+ * Rotates the icon clockwise.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> iconRotate(Function<Float> function) {
+ return new LayoutProperty<>("icon-rotate", function);
+ }
+
+ /**
+ * Size of the additional area around the icon bounding box used for detecting symbol collisions.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> iconPadding(Float value) {
+ return new LayoutProperty<>("icon-padding", value);
+ }
+
+ /**
+ * Size of the additional area around the icon bounding box used for detecting symbol collisions.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> iconPadding(Function<Float> function) {
+ return new LayoutProperty<>("icon-padding", function);
+ }
+
+ /**
+ * If true, the icon may be flipped to prevent it from being rendered upside-down.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static Property<Boolean> iconKeepUpright(Boolean value) {
+ return new LayoutProperty<>("icon-keep-upright", value);
+ }
+
+ /**
+ * If true, the icon may be flipped to prevent it from being rendered upside-down.
+ *
+ * @param function a wrapper function for Boolean
+ * @return property wrapper around a Boolean function
+ */
+ public static Property<Function<Boolean>> iconKeepUpright(Function<Boolean> function) {
+ return new LayoutProperty<>("icon-keep-upright", function);
+ }
+
+ /**
+ * Offset distance of icon from its anchor. Positive values indicate right and down, while negative values indicate
+ * left and up.
+ *
+ * @param value a Float[] value
+ * @return property wrapper around Float[]
+ */
+ public static Property<Float[]> iconOffset(Float[] value) {
+ return new LayoutProperty<>("icon-offset", value);
+ }
+
+ /**
+ * Offset distance of icon from its anchor. Positive values indicate right and down, while negative values indicate
+ * left and up.
+ *
+ * @param function a wrapper function for Float[]
+ * @return property wrapper around a Float[] function
+ */
+ public static Property<Function<Float[]>> iconOffset(Function<Float[]> function) {
+ return new LayoutProperty<>("icon-offset", function);
+ }
+
+ /**
+ * Orientation of text when map is pitched.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> textPitchAlignment(@Property.TEXT_PITCH_ALIGNMENT String value) {
+ return new LayoutProperty<>("text-pitch-alignment", value);
+ }
+
+ /**
+ * Orientation of text when map is pitched.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> textPitchAlignment(Function<String> function) {
+ return new LayoutProperty<>("text-pitch-alignment", function);
+ }
+
+ /**
+ * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of the individual glyphs
+ * forming the text.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> textRotationAlignment(@Property.TEXT_ROTATION_ALIGNMENT String value) {
+ return new LayoutProperty<>("text-rotation-alignment", value);
+ }
+
+ /**
+ * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of the individual glyphs
+ * forming the text.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> textRotationAlignment(Function<String> function) {
+ return new LayoutProperty<>("text-rotation-alignment", function);
+ }
+
+ /**
+ * Value to use for a text label. Feature properties are specified using tokens like {field_name}.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> textField(String value) {
+ return new LayoutProperty<>("text-field", value);
+ }
+
+ /**
+ * Value to use for a text label. Feature properties are specified using tokens like {field_name}.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> textField(Function<String> function) {
+ return new LayoutProperty<>("text-field", function);
+ }
+
+ /**
+ * Font stack to use for displaying text.
+ *
+ * @param value a String[] value
+ * @return property wrapper around String[]
+ */
+ public static Property<String[]> textFont(String[] value) {
+ return new LayoutProperty<>("text-font", value);
+ }
+
+ /**
+ * Font stack to use for displaying text.
+ *
+ * @param function a wrapper function for String[]
+ * @return property wrapper around a String[] function
+ */
+ public static Property<Function<String[]>> textFont(Function<String[]> function) {
+ return new LayoutProperty<>("text-font", function);
+ }
+
+ /**
+ * Font size.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> textSize(Float value) {
+ return new LayoutProperty<>("text-size", value);
+ }
+
+ /**
+ * Font size.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> textSize(Function<Float> function) {
+ return new LayoutProperty<>("text-size", function);
+ }
+
+ /**
+ * The maximum line width for text wrapping.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> textMaxWidth(Float value) {
+ return new LayoutProperty<>("text-max-width", value);
+ }
+
+ /**
+ * The maximum line width for text wrapping.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> textMaxWidth(Function<Float> function) {
+ return new LayoutProperty<>("text-max-width", function);
+ }
+
+ /**
+ * Text leading value for multi-line text.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> textLineHeight(Float value) {
+ return new LayoutProperty<>("text-line-height", value);
+ }
+
+ /**
+ * Text leading value for multi-line text.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> textLineHeight(Function<Float> function) {
+ return new LayoutProperty<>("text-line-height", function);
+ }
+
+ /**
+ * Text tracking amount.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> textLetterSpacing(Float value) {
+ return new LayoutProperty<>("text-letter-spacing", value);
+ }
+
+ /**
+ * Text tracking amount.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> textLetterSpacing(Function<Float> function) {
+ return new LayoutProperty<>("text-letter-spacing", function);
+ }
+
+ /**
+ * Text justification options.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> textJustify(@Property.TEXT_JUSTIFY String value) {
+ return new LayoutProperty<>("text-justify", value);
+ }
+
+ /**
+ * Text justification options.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> textJustify(Function<String> function) {
+ return new LayoutProperty<>("text-justify", function);
+ }
+
+ /**
+ * Part of the text placed closest to the anchor.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> textAnchor(@Property.TEXT_ANCHOR String value) {
+ return new LayoutProperty<>("text-anchor", value);
+ }
+
+ /**
+ * Part of the text placed closest to the anchor.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> textAnchor(Function<String> function) {
+ return new LayoutProperty<>("text-anchor", function);
+ }
+
+ /**
+ * Maximum angle change between adjacent characters.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> textMaxAngle(Float value) {
+ return new LayoutProperty<>("text-max-angle", value);
+ }
+
+ /**
+ * Maximum angle change between adjacent characters.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> textMaxAngle(Function<Float> function) {
+ return new LayoutProperty<>("text-max-angle", function);
+ }
+
+ /**
+ * Rotates the text clockwise.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> textRotate(Float value) {
+ return new LayoutProperty<>("text-rotate", value);
+ }
+
+ /**
+ * Rotates the text clockwise.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> textRotate(Function<Float> function) {
+ return new LayoutProperty<>("text-rotate", function);
+ }
+
+ /**
+ * Size of the additional area around the text bounding box used for detecting symbol collisions.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static Property<Float> textPadding(Float value) {
+ return new LayoutProperty<>("text-padding", value);
+ }
+
+ /**
+ * Size of the additional area around the text bounding box used for detecting symbol collisions.
+ *
+ * @param function a wrapper function for Float
+ * @return property wrapper around a Float function
+ */
+ public static Property<Function<Float>> textPadding(Function<Float> function) {
+ return new LayoutProperty<>("text-padding", function);
+ }
+
+ /**
+ * If true, the text may be flipped vertically to prevent it from being rendered upside-down.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static Property<Boolean> textKeepUpright(Boolean value) {
+ return new LayoutProperty<>("text-keep-upright", value);
+ }
+
+ /**
+ * If true, the text may be flipped vertically to prevent it from being rendered upside-down.
+ *
+ * @param function a wrapper function for Boolean
+ * @return property wrapper around a Boolean function
+ */
+ public static Property<Function<Boolean>> textKeepUpright(Function<Boolean> function) {
+ return new LayoutProperty<>("text-keep-upright", function);
+ }
+
+ /**
+ * Specifies how to capitalize text, similar to the CSS {@link PropertyFactory#textTransform} property.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static Property<String> textTransform(@Property.TEXT_TRANSFORM String value) {
+ return new LayoutProperty<>("text-transform", value);
+ }
+
+ /**
+ * Specifies how to capitalize text, similar to the CSS {@link PropertyFactory#textTransform} property.
+ *
+ * @param function a wrapper function for String
+ * @return property wrapper around a String function
+ */
+ public static Property<Function<String>> textTransform(Function<String> function) {
+ return new LayoutProperty<>("text-transform", function);
+ }
+
+ /**
+ * Offset distance of text from its anchor. Positive values indicate right and down, while negative values indicate
+ * left and up.
+ *
+ * @param value a Float[] value
+ * @return property wrapper around Float[]
+ */
+ public static Property<Float[]> textOffset(Float[] value) {
+ return new LayoutProperty<>("text-offset", value);
+ }
+
+ /**
+ * Offset distance of text from its anchor. Positive values indicate right and down, while negative values indicate
+ * left and up.
+ *
+ * @param function a wrapper function for Float[]
+ * @return property wrapper around a Float[] function
+ */
+ public static Property<Function<Float[]>> textOffset(Function<Float[]> function) {
+ return new LayoutProperty<>("text-offset", function);
+ }
+
+ /**
+ * If true, the text will be visible even if it collides with other previously drawn symbols.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static Property<Boolean> textAllowOverlap(Boolean value) {
+ return new LayoutProperty<>("text-allow-overlap", value);
+ }
+
+ /**
+ * If true, the text will be visible even if it collides with other previously drawn symbols.
+ *
+ * @param function a wrapper function for Boolean
+ * @return property wrapper around a Boolean function
+ */
+ public static Property<Function<Boolean>> textAllowOverlap(Function<Boolean> function) {
+ return new LayoutProperty<>("text-allow-overlap", function);
+ }
+
+ /**
+ * If true, other symbols can be visible even if they collide with the text.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static Property<Boolean> textIgnorePlacement(Boolean value) {
+ return new LayoutProperty<>("text-ignore-placement", value);
+ }
+
+ /**
+ * If true, other symbols can be visible even if they collide with the text.
+ *
+ * @param function a wrapper function for Boolean
+ * @return property wrapper around a Boolean function
+ */
+ public static Property<Function<Boolean>> textIgnorePlacement(Function<Boolean> function) {
+ return new LayoutProperty<>("text-ignore-placement", function);
+ }
+
+ /**
+ * If true, icons will display without their corresponding text when the text collides with other symbols and the
+ * icon does not.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static Property<Boolean> textOptional(Boolean value) {
+ return new LayoutProperty<>("text-optional", value);
+ }
+
+ /**
+ * If true, icons will display without their corresponding text when the text collides with other symbols and the
+ * icon does not.
+ *
+ * @param function a wrapper function for Boolean
+ * @return property wrapper around a Boolean function
+ */
+ public static Property<Function<Boolean>> textOptional(Function<Boolean> function) {
+ return new LayoutProperty<>("text-optional", function);
+ }
+
+ @SuppressLint("DefaultLocale")
+ static String colorToRgbaString(@ColorInt int value) {
+ return String.format("rgba(%d, %d, %d, %d)", (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF,
+ (value >> 24) & 0xFF);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java
index 204c154743..c404f07c76 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java
@@ -1,56 +1,57 @@
package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.Nullable;
-import android.util.Log;
+
+import timber.log.Timber;
/**
* Properties for Layer
*/
public class PropertyValue<T> {
- private static final String TAG = PropertyValue.class.getSimpleName();
- private final Object value;
+ private final Object value;
- /* package */ PropertyValue(Object value) {
- this.value = value;
- }
+ /* package */ PropertyValue(Object value) {
+ this.value = value;
+ }
- public boolean isNull() {
- return value == null;
- }
+ public boolean isNull() {
+ return value == null;
+ }
- public boolean isFunction() {
- return !isNull() && value instanceof Function;
- }
+ public boolean isFunction() {
+ return !isNull() && value instanceof Function;
+ }
- public boolean isValue() {
- return !isNull() && !isFunction();
- }
+ public boolean isValue() {
+ return !isNull() && !isFunction();
+ }
- @Nullable
- public Function<T> getFunction() {
- if (isFunction()) {
- //noinspection unchecked
- return (Function<T>) value;
- } else {
- Log.w(TAG, "not a function, try value");
- return null;
- }
+ @Nullable
+ public Function<T> getFunction() {
+ if (isFunction()) {
+ //noinspection unchecked
+ return (Function<T>) value;
+ } else {
+ Timber.w("not a function, try value");
+ return null;
}
-
- @Nullable
- public T getValue() {
- if (isValue()) {
- //noinspection unchecked
- return (T) value;
- } else {
- Log.w(TAG, "not a value, try function");
- return null;
- }
+ }
+
+ @Nullable
+ public T getValue() {
+ if (isValue()) {
+ //noinspection unchecked
+ return (T) value;
+ } else {
+ Timber.w("not a value, try function");
+ return null;
}
+ }
- @Override
- public String toString() {
- return String.format("%s (%s)", getClass().getSimpleName(), value != null ? value.getClass().getSimpleName() : null);
- }
+ @Override
+ public String toString() {
+ return String.format("%s (%s)", getClass().getSimpleName(), value != null
+ ? value.getClass().getSimpleName() : null);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java
index e5f33aced6..785106c394 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java
@@ -1,168 +1,157 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
-import com.mapbox.mapboxsdk.exceptions.ConversionException;
-
-import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
-
-import static com.mapbox.mapboxsdk.utils.ColorUtils.*;
+import android.support.annotation.UiThread;
/**
* Raster map textures such as satellite imagery.
*
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#layers-raster">The online documentation</a>
*/
+@UiThread
public class RasterLayer extends Layer {
- /**
- * Creates a RasterLayer.
- *
- * @param nativePtr pointer used by core
- */
- public RasterLayer(long nativePtr) {
- super(nativePtr);
- }
-
- /**
- * Creates a RasterLayer.
- *
- * @param layerId the id of the layer
- * @param sourceId the id of the source
- */
- public RasterLayer(String layerId, String sourceId) {
- initialize(layerId, sourceId);
- }
-
- protected native void initialize(String layerId, String sourceId);
-
- /**
- * Set the source layer.
- *
- * @param sourceLayer the source layer to set
- */
- public void setSourceLayer(String sourceLayer) {
- checkValidity();
- nativeSetSourceLayer(sourceLayer);
- }
-
- /**
- * Set the source Layer.
- *
- * @param sourceLayer the source layer to set
- * @return This
- */
- public RasterLayer withSourceLayer(String sourceLayer) {
- setSourceLayer(sourceLayer);
- return this;
- }
-
- /**
- * Set a property or properties.
- *
- * @param properties the var-args properties
- * @return This
- */
- public RasterLayer withProperties(@NonNull Property<?>... properties) {
- setProperties(properties);
- return this;
- }
-
- // Property getters
-
- /**
- * Get the RasterOpacity property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getRasterOpacity() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetRasterOpacity());
- }
-
- /**
- * Get the RasterHueRotate property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getRasterHueRotate() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetRasterHueRotate());
- }
-
- /**
- * Get the RasterBrightnessMin property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getRasterBrightnessMin() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetRasterBrightnessMin());
- }
-
- /**
- * Get the RasterBrightnessMax property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getRasterBrightnessMax() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetRasterBrightnessMax());
- }
-
- /**
- * Get the RasterSaturation property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getRasterSaturation() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetRasterSaturation());
- }
-
- /**
- * Get the RasterContrast property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getRasterContrast() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetRasterContrast());
- }
-
- /**
- * Get the RasterFadeDuration property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getRasterFadeDuration() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetRasterFadeDuration());
- }
-
- private native Object nativeGetRasterOpacity();
-
- private native Object nativeGetRasterHueRotate();
-
- private native Object nativeGetRasterBrightnessMin();
-
- private native Object nativeGetRasterBrightnessMax();
-
- private native Object nativeGetRasterSaturation();
-
- private native Object nativeGetRasterContrast();
-
- private native Object nativeGetRasterFadeDuration();
-
-
- @Override
- protected native void finalize() throws Throwable;
+ /**
+ * Creates a RasterLayer.
+ *
+ * @param nativePtr pointer used by core
+ */
+ public RasterLayer(long nativePtr) {
+ super(nativePtr);
+ }
+
+ /**
+ * Creates a RasterLayer.
+ *
+ * @param layerId the id of the layer
+ * @param sourceId the id of the source
+ */
+ public RasterLayer(String layerId, String sourceId) {
+ initialize(layerId, sourceId);
+ }
+
+ protected native void initialize(String layerId, String sourceId);
+
+ /**
+ * Set the source layer.
+ *
+ * @param sourceLayer the source layer to set
+ */
+ public void setSourceLayer(String sourceLayer) {
+ nativeSetSourceLayer(sourceLayer);
+ }
+
+ /**
+ * Set the source Layer.
+ *
+ * @param sourceLayer the source layer to set
+ * @return This
+ */
+ public RasterLayer withSourceLayer(String sourceLayer) {
+ setSourceLayer(sourceLayer);
+ return this;
+ }
+
+ /**
+ * Set a property or properties.
+ *
+ * @param properties the var-args properties
+ * @return This
+ */
+ public RasterLayer withProperties(@NonNull Property<?>... properties) {
+ setProperties(properties);
+ return this;
+ }
+
+ // Property getters
+
+ /**
+ * Get the RasterOpacity property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getRasterOpacity() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetRasterOpacity());
+ }
+
+ /**
+ * Get the RasterHueRotate property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getRasterHueRotate() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetRasterHueRotate());
+ }
+
+ /**
+ * Get the RasterBrightnessMin property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getRasterBrightnessMin() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetRasterBrightnessMin());
+ }
+
+ /**
+ * Get the RasterBrightnessMax property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getRasterBrightnessMax() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetRasterBrightnessMax());
+ }
+
+ /**
+ * Get the RasterSaturation property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getRasterSaturation() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetRasterSaturation());
+ }
+
+ /**
+ * Get the RasterContrast property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getRasterContrast() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetRasterContrast());
+ }
+
+ /**
+ * Get the RasterFadeDuration property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getRasterFadeDuration() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetRasterFadeDuration());
+ }
+
+ private native Object nativeGetRasterOpacity();
+
+ private native Object nativeGetRasterHueRotate();
+
+ private native Object nativeGetRasterBrightnessMin();
+
+ private native Object nativeGetRasterBrightnessMax();
+
+ private native Object nativeGetRasterSaturation();
+
+ private native Object nativeGetRasterContrast();
+
+ private native Object nativeGetRasterFadeDuration();
+
+
+ @Override
+ protected native void finalize() throws Throwable;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java
index 4ceebd8bc1..abc516d6d0 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java
@@ -1,811 +1,761 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
-
-import com.mapbox.mapboxsdk.exceptions.ConversionException;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.UiThread;
-import static com.mapbox.mapboxsdk.utils.ColorUtils.*;
+import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
/**
* An icon or a text label.
*
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#layers-symbol">The online documentation</a>
*/
+@UiThread
public class SymbolLayer extends Layer {
- /**
- * Creates a SymbolLayer.
- *
- * @param nativePtr pointer used by core
- */
- public SymbolLayer(long nativePtr) {
- super(nativePtr);
- }
-
- /**
- * Creates a SymbolLayer.
- *
- * @param layerId the id of the layer
- * @param sourceId the id of the source
- */
- public SymbolLayer(String layerId, String sourceId) {
- initialize(layerId, sourceId);
- }
-
- protected native void initialize(String layerId, String sourceId);
-
- /**
- * Set the source layer.
- *
- * @param sourceLayer the source layer to set
- */
- public void setSourceLayer(String sourceLayer) {
- checkValidity();
- nativeSetSourceLayer(sourceLayer);
- }
-
- /**
- * Set the source Layer.
- *
- * @param sourceLayer the source layer to set
- * @return This
- */
- public SymbolLayer withSourceLayer(String sourceLayer) {
- setSourceLayer(sourceLayer);
- return this;
- }
- /**
- * Set a single filter.
- *
- * @param filter the filter to set
- */
- public void setFilter(Filter.Statement filter) {
- checkValidity();
- this.setFilter(filter.toArray());
- }
-
- /**
- * Set an array of filters.
- *
- * @param filter the filter array to set
- */
- public void setFilter(Object[] filter) {
- checkValidity();
- nativeSetFilter(filter);
- }
-
- /**
- * Set an array of filters.
- *
- * @param filter tthe filter array to set
- * @return This
- */
- public SymbolLayer withFilter(Object[] filter) {
- setFilter(filter);
- return this;
- }
-
- /**
- * Set a single filter.
- *
- * @param filter the filter to set
- * @return This
- */
- public SymbolLayer withFilter(Filter.Statement filter) {
- setFilter(filter);
- return this;
- }
-
-
- /**
- * Set a property or properties.
- *
- * @param properties the var-args properties
- * @return This
- */
- public SymbolLayer withProperties(@NonNull Property<?>... properties) {
- setProperties(properties);
- return this;
- }
-
- // Property getters
-
- /**
- * Get the SymbolPlacement property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getSymbolPlacement() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetSymbolPlacement());
- }
-
- /**
- * Get the SymbolSpacing property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getSymbolSpacing() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetSymbolSpacing());
- }
-
- /**
- * Get the SymbolAvoidEdges property
- *
- * @return property wrapper value around Boolean
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Boolean> getSymbolAvoidEdges() {
- checkValidity();
- return (PropertyValue<Boolean>) new PropertyValue(nativeGetSymbolAvoidEdges());
- }
-
- /**
- * Get the IconAllowOverlap property
- *
- * @return property wrapper value around Boolean
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Boolean> getIconAllowOverlap() {
- checkValidity();
- return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconAllowOverlap());
- }
-
- /**
- * Get the IconIgnorePlacement property
- *
- * @return property wrapper value around Boolean
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Boolean> getIconIgnorePlacement() {
- checkValidity();
- return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconIgnorePlacement());
- }
-
- /**
- * Get the IconOptional property
- *
- * @return property wrapper value around Boolean
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Boolean> getIconOptional() {
- checkValidity();
- return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconOptional());
- }
-
- /**
- * Get the IconRotationAlignment property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getIconRotationAlignment() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetIconRotationAlignment());
- }
-
- /**
- * Get the IconSize property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getIconSize() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetIconSize());
- }
-
- /**
- * Get the IconTextFit property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getIconTextFit() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetIconTextFit());
- }
-
- /**
- * Get the IconTextFitPadding property
- *
- * @return property wrapper value around Float[]
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float[]> getIconTextFitPadding() {
- checkValidity();
- return (PropertyValue<Float[]>) new PropertyValue(nativeGetIconTextFitPadding());
- }
-
- /**
- * Get the IconImage property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getIconImage() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetIconImage());
- }
-
- /**
- * Get the IconRotate property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getIconRotate() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetIconRotate());
- }
-
- /**
- * Get the IconPadding property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getIconPadding() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetIconPadding());
- }
-
- /**
- * Get the IconKeepUpright property
- *
- * @return property wrapper value around Boolean
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Boolean> getIconKeepUpright() {
- checkValidity();
- return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconKeepUpright());
- }
-
- /**
- * Get the IconOffset property
- *
- * @return property wrapper value around Float[]
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float[]> getIconOffset() {
- checkValidity();
- return (PropertyValue<Float[]>) new PropertyValue(nativeGetIconOffset());
- }
-
- /**
- * Get the TextPitchAlignment property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getTextPitchAlignment() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetTextPitchAlignment());
- }
-
- /**
- * Get the TextRotationAlignment property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getTextRotationAlignment() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetTextRotationAlignment());
- }
-
- /**
- * Get the TextField property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getTextField() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetTextField());
- }
-
- /**
- * Get the TextFont property
- *
- * @return property wrapper value around String[]
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String[]> getTextFont() {
- checkValidity();
- return (PropertyValue<String[]>) new PropertyValue(nativeGetTextFont());
- }
-
- /**
- * Get the TextSize property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getTextSize() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetTextSize());
- }
-
- /**
- * Get the TextMaxWidth property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getTextMaxWidth() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetTextMaxWidth());
- }
-
- /**
- * Get the TextLineHeight property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getTextLineHeight() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetTextLineHeight());
- }
-
- /**
- * Get the TextLetterSpacing property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getTextLetterSpacing() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetTextLetterSpacing());
- }
-
- /**
- * Get the TextJustify property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getTextJustify() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetTextJustify());
- }
-
- /**
- * Get the TextAnchor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getTextAnchor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetTextAnchor());
- }
-
- /**
- * Get the TextMaxAngle property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getTextMaxAngle() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetTextMaxAngle());
- }
-
- /**
- * Get the TextRotate property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getTextRotate() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetTextRotate());
- }
-
- /**
- * Get the TextPadding property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getTextPadding() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetTextPadding());
- }
-
- /**
- * Get the TextKeepUpright property
- *
- * @return property wrapper value around Boolean
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Boolean> getTextKeepUpright() {
- checkValidity();
- return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextKeepUpright());
- }
-
- /**
- * Get the TextTransform property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getTextTransform() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetTextTransform());
- }
-
- /**
- * Get the TextOffset property
- *
- * @return property wrapper value around Float[]
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float[]> getTextOffset() {
- checkValidity();
- return (PropertyValue<Float[]>) new PropertyValue(nativeGetTextOffset());
- }
-
- /**
- * Get the TextAllowOverlap property
- *
- * @return property wrapper value around Boolean
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Boolean> getTextAllowOverlap() {
- checkValidity();
- return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextAllowOverlap());
- }
-
- /**
- * Get the TextIgnorePlacement property
- *
- * @return property wrapper value around Boolean
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Boolean> getTextIgnorePlacement() {
- checkValidity();
- return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextIgnorePlacement());
- }
-
- /**
- * Get the TextOptional property
- *
- * @return property wrapper value around Boolean
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Boolean> getTextOptional() {
- checkValidity();
- return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextOptional());
- }
-
- /**
- * Get the IconOpacity property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getIconOpacity() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetIconOpacity());
- }
-
- /**
- * Get the IconColor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getIconColor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetIconColor());
- }
- /**
- * The color of the icon. This can only be used with sdf icons.
- *
- * @return int representation of a rgba string color
- * @throws RuntimeException thrown if property isn't a value
- */
- @ColorInt
- public int getIconColorAsInt() {
- checkValidity();
- PropertyValue<String> value = getIconColor();
- if (value.isValue()) {
- return rgbaToColor(value.getValue());
- } else {
- throw new RuntimeException("icon-color was set as a Function");
- }
- }
+ /**
+ * Creates a SymbolLayer.
+ *
+ * @param nativePtr pointer used by core
+ */
+ public SymbolLayer(long nativePtr) {
+ super(nativePtr);
+ }
+
+ /**
+ * Creates a SymbolLayer.
+ *
+ * @param layerId the id of the layer
+ * @param sourceId the id of the source
+ */
+ public SymbolLayer(String layerId, String sourceId) {
+ initialize(layerId, sourceId);
+ }
+
+ protected native void initialize(String layerId, String sourceId);
+
+ /**
+ * Set the source layer.
+ *
+ * @param sourceLayer the source layer to set
+ */
+ public void setSourceLayer(String sourceLayer) {
+ nativeSetSourceLayer(sourceLayer);
+ }
+
+ /**
+ * Set the source Layer.
+ *
+ * @param sourceLayer the source layer to set
+ * @return This
+ */
+ public SymbolLayer withSourceLayer(String sourceLayer) {
+ setSourceLayer(sourceLayer);
+ return this;
+ }
+
+ /**
+ * Set a single filter.
+ *
+ * @param filter the filter to set
+ */
+ public void setFilter(Filter.Statement filter) {
+ this.setFilter(filter.toArray());
+ }
+
+ /**
+ * Set an array of filters.
+ *
+ * @param filter the filter array to set
+ */
+ public void setFilter(Object[] filter) {
+ nativeSetFilter(filter);
+ }
+
+ /**
+ * Set an array of filters.
+ *
+ * @param filter tthe filter array to set
+ * @return This
+ */
+ public SymbolLayer withFilter(Object[] filter) {
+ setFilter(filter);
+ return this;
+ }
+
+ /**
+ * Set a single filter.
+ *
+ * @param filter the filter to set
+ * @return This
+ */
+ public SymbolLayer withFilter(Filter.Statement filter) {
+ setFilter(filter);
+ return this;
+ }
+
+
+ /**
+ * Set a property or properties.
+ *
+ * @param properties the var-args properties
+ * @return This
+ */
+ public SymbolLayer withProperties(@NonNull Property<?>... properties) {
+ setProperties(properties);
+ return this;
+ }
+
+ // Property getters
+
+ /**
+ * Get the SymbolPlacement property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getSymbolPlacement() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetSymbolPlacement());
+ }
+
+ /**
+ * Get the SymbolSpacing property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getSymbolSpacing() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetSymbolSpacing());
+ }
+
+ /**
+ * Get the SymbolAvoidEdges property
+ *
+ * @return property wrapper value around Boolean
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Boolean> getSymbolAvoidEdges() {
+ return (PropertyValue<Boolean>) new PropertyValue(nativeGetSymbolAvoidEdges());
+ }
+
+ /**
+ * Get the IconAllowOverlap property
+ *
+ * @return property wrapper value around Boolean
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Boolean> getIconAllowOverlap() {
+ return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconAllowOverlap());
+ }
+
+ /**
+ * Get the IconIgnorePlacement property
+ *
+ * @return property wrapper value around Boolean
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Boolean> getIconIgnorePlacement() {
+ return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconIgnorePlacement());
+ }
+
+ /**
+ * Get the IconOptional property
+ *
+ * @return property wrapper value around Boolean
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Boolean> getIconOptional() {
+ return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconOptional());
+ }
+
+ /**
+ * Get the IconRotationAlignment property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getIconRotationAlignment() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetIconRotationAlignment());
+ }
+
+ /**
+ * Get the IconSize property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getIconSize() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetIconSize());
+ }
+
+ /**
+ * Get the IconTextFit property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getIconTextFit() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetIconTextFit());
+ }
+
+ /**
+ * Get the IconTextFitPadding property
+ *
+ * @return property wrapper value around Float[]
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float[]> getIconTextFitPadding() {
+ return (PropertyValue<Float[]>) new PropertyValue(nativeGetIconTextFitPadding());
+ }
+
+ /**
+ * Get the IconImage property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getIconImage() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetIconImage());
+ }
+
+ /**
+ * Get the IconRotate property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getIconRotate() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetIconRotate());
+ }
+
+ /**
+ * Get the IconPadding property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getIconPadding() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetIconPadding());
+ }
+
+ /**
+ * Get the IconKeepUpright property
+ *
+ * @return property wrapper value around Boolean
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Boolean> getIconKeepUpright() {
+ return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconKeepUpright());
+ }
+
+ /**
+ * Get the IconOffset property
+ *
+ * @return property wrapper value around Float[]
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float[]> getIconOffset() {
+ return (PropertyValue<Float[]>) new PropertyValue(nativeGetIconOffset());
+ }
+
+ /**
+ * Get the TextPitchAlignment property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getTextPitchAlignment() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetTextPitchAlignment());
+ }
+
+ /**
+ * Get the TextRotationAlignment property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getTextRotationAlignment() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetTextRotationAlignment());
+ }
+
+ /**
+ * Get the TextField property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getTextField() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetTextField());
+ }
+
+ /**
+ * Get the TextFont property
+ *
+ * @return property wrapper value around String[]
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String[]> getTextFont() {
+ return (PropertyValue<String[]>) new PropertyValue(nativeGetTextFont());
+ }
+
+ /**
+ * Get the TextSize property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getTextSize() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetTextSize());
+ }
+
+ /**
+ * Get the TextMaxWidth property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getTextMaxWidth() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetTextMaxWidth());
+ }
+
+ /**
+ * Get the TextLineHeight property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getTextLineHeight() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetTextLineHeight());
+ }
+
+ /**
+ * Get the TextLetterSpacing property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getTextLetterSpacing() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetTextLetterSpacing());
+ }
+
+ /**
+ * Get the TextJustify property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getTextJustify() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetTextJustify());
+ }
+
+ /**
+ * Get the TextAnchor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getTextAnchor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetTextAnchor());
+ }
+
+ /**
+ * Get the TextMaxAngle property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getTextMaxAngle() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetTextMaxAngle());
+ }
+
+ /**
+ * Get the TextRotate property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getTextRotate() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetTextRotate());
+ }
+
+ /**
+ * Get the TextPadding property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getTextPadding() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetTextPadding());
+ }
+
+ /**
+ * Get the TextKeepUpright property
+ *
+ * @return property wrapper value around Boolean
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Boolean> getTextKeepUpright() {
+ return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextKeepUpright());
+ }
+
+ /**
+ * Get the TextTransform property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getTextTransform() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetTextTransform());
+ }
+
+ /**
+ * Get the TextOffset property
+ *
+ * @return property wrapper value around Float[]
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float[]> getTextOffset() {
+ return (PropertyValue<Float[]>) new PropertyValue(nativeGetTextOffset());
+ }
+
+ /**
+ * Get the TextAllowOverlap property
+ *
+ * @return property wrapper value around Boolean
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Boolean> getTextAllowOverlap() {
+ return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextAllowOverlap());
+ }
+
+ /**
+ * Get the TextIgnorePlacement property
+ *
+ * @return property wrapper value around Boolean
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Boolean> getTextIgnorePlacement() {
+ return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextIgnorePlacement());
+ }
+
+ /**
+ * Get the TextOptional property
+ *
+ * @return property wrapper value around Boolean
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Boolean> getTextOptional() {
+ return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextOptional());
+ }
+
+ /**
+ * Get the IconOpacity property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getIconOpacity() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetIconOpacity());
+ }
+
+ /**
+ * Get the IconColor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getIconColor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetIconColor());
+ }
+
+ /**
+ * The color of the icon. This can only be used with sdf icons.
+ *
+ * @return int representation of a rgba string color
+ * @throws RuntimeException thrown if property isn't a value
+ */
+ @ColorInt
+ public int getIconColorAsInt() {
+ PropertyValue<String> value = getIconColor();
+ if (value.isValue()) {
+ return rgbaToColor(value.getValue());
+ } else {
+ throw new RuntimeException("icon-color was set as a Function");
+ }
+ }
+
+
+ /**
+ * Get the IconHaloColor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getIconHaloColor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetIconHaloColor());
+ }
+
+ /**
+ * The color of the icon's halo. Icon halos can only be used with SDF icons.
+ *
+ * @return int representation of a rgba string color
+ * @throws RuntimeException thrown if property isn't a value
+ */
+ @ColorInt
+ public int getIconHaloColorAsInt() {
+ PropertyValue<String> value = getIconHaloColor();
+ if (value.isValue()) {
+ return rgbaToColor(value.getValue());
+ } else {
+ throw new RuntimeException("icon-halo-color was set as a Function");
+ }
+ }
+
+
+ /**
+ * Get the IconHaloWidth property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getIconHaloWidth() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetIconHaloWidth());
+ }
+
+ /**
+ * Get the IconHaloBlur property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getIconHaloBlur() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetIconHaloBlur());
+ }
+
+ /**
+ * Get the IconTranslate property
+ *
+ * @return property wrapper value around Float[]
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float[]> getIconTranslate() {
+ return (PropertyValue<Float[]>) new PropertyValue(nativeGetIconTranslate());
+ }
+
+ /**
+ * Get the IconTranslateAnchor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getIconTranslateAnchor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetIconTranslateAnchor());
+ }
+
+ /**
+ * Get the TextOpacity property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getTextOpacity() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetTextOpacity());
+ }
+
+ /**
+ * Get the TextColor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getTextColor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetTextColor());
+ }
+
+ /**
+ * The color with which the text will be drawn.
+ *
+ * @return int representation of a rgba string color
+ * @throws RuntimeException thrown if property isn't a value
+ */
+ @ColorInt
+ public int getTextColorAsInt() {
+ PropertyValue<String> value = getTextColor();
+ if (value.isValue()) {
+ return rgbaToColor(value.getValue());
+ } else {
+ throw new RuntimeException("text-color was set as a Function");
+ }
+ }
+
+
+ /**
+ * Get the TextHaloColor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getTextHaloColor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetTextHaloColor());
+ }
+
+ /**
+ * The color of the text's halo, which helps it stand out from backgrounds.
+ *
+ * @return int representation of a rgba string color
+ * @throws RuntimeException thrown if property isn't a value
+ */
+ @ColorInt
+ public int getTextHaloColorAsInt() {
+ PropertyValue<String> value = getTextHaloColor();
+ if (value.isValue()) {
+ return rgbaToColor(value.getValue());
+ } else {
+ throw new RuntimeException("text-halo-color was set as a Function");
+ }
+ }
+
+
+ /**
+ * Get the TextHaloWidth property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getTextHaloWidth() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetTextHaloWidth());
+ }
-
- /**
- * Get the IconHaloColor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getIconHaloColor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetIconHaloColor());
- }
- /**
- * The color of the icon's halo. Icon halos can only be used with SDF icons.
- *
- * @return int representation of a rgba string color
- * @throws RuntimeException thrown if property isn't a value
- */
- @ColorInt
- public int getIconHaloColorAsInt() {
- checkValidity();
- PropertyValue<String> value = getIconHaloColor();
- if (value.isValue()) {
- return rgbaToColor(value.getValue());
- } else {
- throw new RuntimeException("icon-halo-color was set as a Function");
- }
- }
+ /**
+ * Get the TextHaloBlur property
+ *
+ * @return property wrapper value around Float
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getTextHaloBlur() {
+ return (PropertyValue<Float>) new PropertyValue(nativeGetTextHaloBlur());
+ }
-
- /**
- * Get the IconHaloWidth property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getIconHaloWidth() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetIconHaloWidth());
- }
-
- /**
- * Get the IconHaloBlur property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getIconHaloBlur() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetIconHaloBlur());
- }
-
- /**
- * Get the IconTranslate property
- *
- * @return property wrapper value around Float[]
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float[]> getIconTranslate() {
- checkValidity();
- return (PropertyValue<Float[]>) new PropertyValue(nativeGetIconTranslate());
- }
-
- /**
- * Get the IconTranslateAnchor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getIconTranslateAnchor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetIconTranslateAnchor());
- }
-
- /**
- * Get the TextOpacity property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getTextOpacity() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetTextOpacity());
- }
-
- /**
- * Get the TextColor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getTextColor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetTextColor());
- }
- /**
- * The color with which the text will be drawn.
- *
- * @return int representation of a rgba string color
- * @throws RuntimeException thrown if property isn't a value
- */
- @ColorInt
- public int getTextColorAsInt() {
- checkValidity();
- PropertyValue<String> value = getTextColor();
- if (value.isValue()) {
- return rgbaToColor(value.getValue());
- } else {
- throw new RuntimeException("text-color was set as a Function");
- }
- }
+ /**
+ * Get the TextTranslate property
+ *
+ * @return property wrapper value around Float[]
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float[]> getTextTranslate() {
+ return (PropertyValue<Float[]>) new PropertyValue(nativeGetTextTranslate());
+ }
-
- /**
- * Get the TextHaloColor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getTextHaloColor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetTextHaloColor());
- }
- /**
- * The color of the text's halo, which helps it stand out from backgrounds.
- *
- * @return int representation of a rgba string color
- * @throws RuntimeException thrown if property isn't a value
- */
- @ColorInt
- public int getTextHaloColorAsInt() {
- checkValidity();
- PropertyValue<String> value = getTextHaloColor();
- if (value.isValue()) {
- return rgbaToColor(value.getValue());
- } else {
- throw new RuntimeException("text-halo-color was set as a Function");
- }
- }
+ /**
+ * Get the TextTranslateAnchor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getTextTranslateAnchor() {
+ return (PropertyValue<String>) new PropertyValue(nativeGetTextTranslateAnchor());
+ }
-
- /**
- * Get the TextHaloWidth property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getTextHaloWidth() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetTextHaloWidth());
- }
-
- /**
- * Get the TextHaloBlur property
- *
- * @return property wrapper value around Float
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float> getTextHaloBlur() {
- checkValidity();
- return (PropertyValue<Float>) new PropertyValue(nativeGetTextHaloBlur());
- }
-
- /**
- * Get the TextTranslate property
- *
- * @return property wrapper value around Float[]
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<Float[]> getTextTranslate() {
- checkValidity();
- return (PropertyValue<Float[]>) new PropertyValue(nativeGetTextTranslate());
- }
-
- /**
- * Get the TextTranslateAnchor property
- *
- * @return property wrapper value around String
- */
- @SuppressWarnings("unchecked")
- public PropertyValue<String> getTextTranslateAnchor() {
- checkValidity();
- return (PropertyValue<String>) new PropertyValue(nativeGetTextTranslateAnchor());
- }
-
- private native Object nativeGetSymbolPlacement();
+ private native Object nativeGetSymbolPlacement();
- private native Object nativeGetSymbolSpacing();
+ private native Object nativeGetSymbolSpacing();
- private native Object nativeGetSymbolAvoidEdges();
+ private native Object nativeGetSymbolAvoidEdges();
- private native Object nativeGetIconAllowOverlap();
+ private native Object nativeGetIconAllowOverlap();
- private native Object nativeGetIconIgnorePlacement();
+ private native Object nativeGetIconIgnorePlacement();
- private native Object nativeGetIconOptional();
+ private native Object nativeGetIconOptional();
- private native Object nativeGetIconRotationAlignment();
+ private native Object nativeGetIconRotationAlignment();
- private native Object nativeGetIconSize();
+ private native Object nativeGetIconSize();
- private native Object nativeGetIconTextFit();
+ private native Object nativeGetIconTextFit();
- private native Object nativeGetIconTextFitPadding();
+ private native Object nativeGetIconTextFitPadding();
- private native Object nativeGetIconImage();
+ private native Object nativeGetIconImage();
- private native Object nativeGetIconRotate();
+ private native Object nativeGetIconRotate();
- private native Object nativeGetIconPadding();
+ private native Object nativeGetIconPadding();
- private native Object nativeGetIconKeepUpright();
+ private native Object nativeGetIconKeepUpright();
- private native Object nativeGetIconOffset();
+ private native Object nativeGetIconOffset();
- private native Object nativeGetTextPitchAlignment();
+ private native Object nativeGetTextPitchAlignment();
- private native Object nativeGetTextRotationAlignment();
+ private native Object nativeGetTextRotationAlignment();
- private native Object nativeGetTextField();
+ private native Object nativeGetTextField();
- private native Object nativeGetTextFont();
+ private native Object nativeGetTextFont();
- private native Object nativeGetTextSize();
+ private native Object nativeGetTextSize();
- private native Object nativeGetTextMaxWidth();
+ private native Object nativeGetTextMaxWidth();
- private native Object nativeGetTextLineHeight();
+ private native Object nativeGetTextLineHeight();
- private native Object nativeGetTextLetterSpacing();
+ private native Object nativeGetTextLetterSpacing();
- private native Object nativeGetTextJustify();
+ private native Object nativeGetTextJustify();
- private native Object nativeGetTextAnchor();
+ private native Object nativeGetTextAnchor();
- private native Object nativeGetTextMaxAngle();
+ private native Object nativeGetTextMaxAngle();
- private native Object nativeGetTextRotate();
+ private native Object nativeGetTextRotate();
- private native Object nativeGetTextPadding();
+ private native Object nativeGetTextPadding();
- private native Object nativeGetTextKeepUpright();
+ private native Object nativeGetTextKeepUpright();
- private native Object nativeGetTextTransform();
+ private native Object nativeGetTextTransform();
- private native Object nativeGetTextOffset();
+ private native Object nativeGetTextOffset();
- private native Object nativeGetTextAllowOverlap();
+ private native Object nativeGetTextAllowOverlap();
- private native Object nativeGetTextIgnorePlacement();
+ private native Object nativeGetTextIgnorePlacement();
- private native Object nativeGetTextOptional();
+ private native Object nativeGetTextOptional();
- private native Object nativeGetIconOpacity();
+ private native Object nativeGetIconOpacity();
- private native Object nativeGetIconColor();
+ private native Object nativeGetIconColor();
- private native Object nativeGetIconHaloColor();
+ private native Object nativeGetIconHaloColor();
- private native Object nativeGetIconHaloWidth();
+ private native Object nativeGetIconHaloWidth();
- private native Object nativeGetIconHaloBlur();
+ private native Object nativeGetIconHaloBlur();
- private native Object nativeGetIconTranslate();
+ private native Object nativeGetIconTranslate();
- private native Object nativeGetIconTranslateAnchor();
+ private native Object nativeGetIconTranslateAnchor();
- private native Object nativeGetTextOpacity();
+ private native Object nativeGetTextOpacity();
- private native Object nativeGetTextColor();
+ private native Object nativeGetTextColor();
- private native Object nativeGetTextHaloColor();
+ private native Object nativeGetTextHaloColor();
- private native Object nativeGetTextHaloWidth();
+ private native Object nativeGetTextHaloWidth();
- private native Object nativeGetTextHaloBlur();
+ private native Object nativeGetTextHaloBlur();
- private native Object nativeGetTextTranslate();
+ private native Object nativeGetTextTranslate();
- private native Object nativeGetTextTranslateAnchor();
+ private native Object nativeGetTextTranslateAnchor();
- @Override
- protected native void finalize() throws Throwable;
+ @Override
+ protected native void finalize() throws Throwable;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/layer.java.ejs b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/layer.java.ejs
index f7865c6b6c..4657037df8 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/layer.java.ejs
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/layer.java.ejs
@@ -3,10 +3,10 @@
const properties = locals.properties;
const doc = locals.doc;
-%>
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
package com.mapbox.mapboxsdk.style.layers;
-import com.mapbox.mapboxsdk.exceptions.ConversionException;
+import android.support.annotation.UiThread;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
@@ -18,6 +18,7 @@ import static com.mapbox.mapboxsdk.utils.ColorUtils.*;
*
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#layers-<%- type %>">The online documentation</a>
*/
+@UiThread
public class <%- camelize(type) %>Layer extends Layer {
/**
@@ -59,7 +60,6 @@ public class <%- camelize(type) %>Layer extends Layer {
* @param sourceLayer the source layer to set
*/
public void setSourceLayer(String sourceLayer) {
- checkValidity();
nativeSetSourceLayer(sourceLayer);
}
@@ -81,7 +81,6 @@ public class <%- camelize(type) %>Layer extends Layer {
* @param filter the filter to set
*/
public void setFilter(Filter.Statement filter) {
- checkValidity();
this.setFilter(filter.toArray());
}
@@ -91,7 +90,6 @@ public class <%- camelize(type) %>Layer extends Layer {
* @param filter the filter array to set
*/
public void setFilter(Object[] filter) {
- checkValidity();
nativeSetFilter(filter);
}
@@ -140,7 +138,6 @@ public class <%- camelize(type) %>Layer extends Layer {
*/
@SuppressWarnings("unchecked")
public PropertyValue<<%- propertyType(property) %>> get<%- camelize(property.name) %>() {
- checkValidity();
return (PropertyValue<<%- propertyType(property) %>>) new PropertyValue(nativeGet<%- camelize(property.name) %>());
}
<% if (property.type == 'color') { -%>
@@ -152,7 +149,6 @@ public class <%- camelize(type) %>Layer extends Layer {
*/
@ColorInt
public int get<%- camelize(property.name) %>AsInt() {
- checkValidity();
PropertyValue<<%- propertyType(property) %>> value = get<%- camelize(property.name) %>();
if (value.isValue()) {
return rgbaToColor(value.getValue());
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property.java.ejs b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property.java.ejs
index bad6f87a8e..3ce691775c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property.java.ejs
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property.java.ejs
@@ -1,7 +1,7 @@
<%
const properties = locals.properties;
-%>
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.StringDef;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs
index a6e2aff839..e9b7b6dcd1 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs
@@ -2,7 +2,7 @@
const paintProperties = locals.paintProperties;
const layoutProperties = locals.layoutProperties;
-%>
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
package com.mapbox.mapboxsdk.style.layers;
import android.annotation.SuppressLint;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.java
new file mode 100644
index 0000000000..ddc4c58cf1
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.java
@@ -0,0 +1,12 @@
+package com.mapbox.mapboxsdk.style.sources;
+
+/**
+ * Thrown when adding a source to a map twice
+ */
+public class CannotAddSourceException extends RuntimeException {
+
+ public CannotAddSourceException(String message) {
+ super(message);
+ }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java
index 55a9799cb7..27a3d5c898 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java
@@ -9,70 +9,72 @@ import java.util.HashMap;
*/
public class GeoJsonOptions extends HashMap<String, Object> {
- /**
- * Maximum zoom level at which to create vector tiles (higher means greater detail at high zoom levels).
- *
- * @param maxZoom the maximum zoom - Defaults to 18.
- * @return the current instance for chaining
- */
- public GeoJsonOptions withMaxZoom(int maxZoom) {
- this.put("maxzoom", maxZoom);
- return this;
- }
+ /**
+ * Maximum zoom level at which to create vector tiles (higher means greater detail at high zoom levels).
+ *
+ * @param maxZoom the maximum zoom - Defaults to 18.
+ * @return the current instance for chaining
+ */
+ public GeoJsonOptions withMaxZoom(int maxZoom) {
+ this.put("maxzoom", maxZoom);
+ return this;
+ }
- /**
- * Tile buffer size on each side (measured in 1/512ths of a tile; higher means fewer rendering artifacts near tile edges but slower performance).
- *
- * @param buffer the buffer size - Defaults to 128.
- * @return the current instance for chaining
- */
- public GeoJsonOptions withBuffer(int buffer) {
- this.put("buffer", buffer);
- return this;
- }
+ /**
+ * Tile buffer size on each side (measured in 1/512ths of a tile; higher means fewer rendering artifacts near tile
+ * edges but slower performance).
+ *
+ * @param buffer the buffer size - Defaults to 128.
+ * @return the current instance for chaining
+ */
+ public GeoJsonOptions withBuffer(int buffer) {
+ this.put("buffer", buffer);
+ return this;
+ }
- /**
- * Douglas-Peucker simplification tolerance (higher means simpler geometries and faster performance).
- *
- * @param tolerance the tolerance - Defaults to 0.375
- * @return the current instance for chaining
- */
- public GeoJsonOptions withTolerance(float tolerance) {
- this.put("tolerance", tolerance);
- return this;
- }
+ /**
+ * Douglas-Peucker simplification tolerance (higher means simpler geometries and faster performance).
+ *
+ * @param tolerance the tolerance - Defaults to 0.375
+ * @return the current instance for chaining
+ */
+ public GeoJsonOptions withTolerance(float tolerance) {
+ this.put("tolerance", tolerance);
+ return this;
+ }
- /**
- * If the data is a collection of point features, setting this to true clusters the points by radius into groups.
- *
- * @param cluster cluster? - Defaults to false
- * @return the current instance for chaining
- */
- public GeoJsonOptions withCluster(boolean cluster) {
- this.put("cluster", cluster);
- return this;
- }
+ /**
+ * If the data is a collection of point features, setting this to true clusters the points by radius into groups.
+ *
+ * @param cluster cluster? - Defaults to false
+ * @return the current instance for chaining
+ */
+ public GeoJsonOptions withCluster(boolean cluster) {
+ this.put("cluster", cluster);
+ return this;
+ }
- /**
- * Max zoom to cluster points on.
- *
- * @param clusterMaxZoom clusterMaxZoom cluster maximum zoom - Defaults to one zoom less than maxzoom (so that last zoom features are not clustered)
- * @return the current instance for chaining
- */
- public GeoJsonOptions withClusterMaxZoom(int clusterMaxZoom) {
- this.put("clusterMaxZoom", clusterMaxZoom);
- return this;
- }
+ /**
+ * Max zoom to cluster points on.
+ *
+ * @param clusterMaxZoom clusterMaxZoom cluster maximum zoom - Defaults to one zoom less than maxzoom (so that last
+ * zoom features are not clustered)
+ * @return the current instance for chaining
+ */
+ public GeoJsonOptions withClusterMaxZoom(int clusterMaxZoom) {
+ this.put("clusterMaxZoom", clusterMaxZoom);
+ return this;
+ }
- /**
- * Radius of each cluster when clustering points, measured in 1/512ths of a tile.
- *
- * @param clusterRadius cluster radius - Defaults to 50
- * @return the current instance for chaining
- */
- public GeoJsonOptions withClusterRadius(int clusterRadius) {
- this.put("clusterRadius", clusterRadius);
- return this;
- }
+ /**
+ * Radius of each cluster when clustering points, measured in 1/512ths of a tile.
+ *
+ * @param clusterRadius cluster radius - Defaults to 50
+ * @return the current instance for chaining
+ */
+ public GeoJsonOptions withClusterRadius(int clusterRadius) {
+ this.put("clusterRadius", clusterRadius);
+ return this;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java
index 80730d143c..0c2ee42ea0 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java
@@ -14,166 +14,166 @@ import java.util.HashMap;
*/
public class GeoJsonSource extends Source {
- /**
- * Internal use
- *
- * @param nativePtr - pointer to native peer
- */
- public GeoJsonSource(long nativePtr) {
- super(nativePtr);
+ /**
+ * Internal use
+ *
+ * @param nativePtr - pointer to native peer
+ */
+ public GeoJsonSource(long nativePtr) {
+ super(nativePtr);
+ }
+
+ /**
+ * Create an empty GeoJsonSource
+ *
+ * @param id the source id
+ */
+ public GeoJsonSource(String id) {
+ initialize(id, null);
+ setGeoJson(FeatureCollection.fromFeatures(new ArrayList<Feature>()));
+ }
+
+ /**
+ * Create an empty GeoJsonSource with non-default {@link GeoJsonOptions}
+ *
+ * @param id the source id
+ * @param options options
+ */
+ public GeoJsonSource(String id, GeoJsonOptions options) {
+ initialize(id, options);
+ setGeoJson(FeatureCollection.fromFeatures(new ArrayList<Feature>()));
+ }
+
+ /**
+ * Create a GeoJsonSource from a raw json string
+ *
+ * @param id the source id
+ * @param geoJson raw Json FeatureCollection
+ */
+ public GeoJsonSource(String id, String geoJson) {
+ if (geoJson == null || geoJson.startsWith("http")) {
+ throw new IllegalArgumentException("Expected a raw json body");
}
-
- /**
- * Create an empty GeoJsonSource
- *
- * @param id the source id
- */
- public GeoJsonSource(String id) {
- initialize(id, null);
- setGeoJson(FeatureCollection.fromFeatures(new ArrayList<Feature>()));
- }
-
- /**
- * Create an empty GeoJsonSource with non-default {@link GeoJsonOptions}
- *
- * @param id the source id
- * @param options options
- */
- public GeoJsonSource(String id, GeoJsonOptions options) {
- initialize(id, options);
- setGeoJson(FeatureCollection.fromFeatures(new ArrayList<Feature>()));
- }
-
- /**
- * Create a GeoJsonSource from a raw json string
- *
- * @param id the source id
- * @param geoJson raw Json FeatureCollection
- */
- public GeoJsonSource(String id, String geoJson) {
- if (geoJson == null || geoJson.startsWith("http")) {
- throw new IllegalArgumentException("Expected a raw json body");
- }
- initialize(id, null);
- setGeoJson(geoJson);
- }
-
- /**
- * Create a GeoJsonSource from a raw json string and non-default {@link GeoJsonOptions}
- *
- * @param id the source id
- * @param geoJson raw Json body
- * @param options options
- */
- public GeoJsonSource(String id, String geoJson, GeoJsonOptions options) {
- if (geoJson == null || geoJson.startsWith("http")) {
- throw new IllegalArgumentException("Expected a raw json body");
- }
- initialize(id, options);
- setGeoJson(geoJson);
- }
-
- /**
- * Create a GeoJsonSource from a remote geo json file
- *
- * @param id the source id
- * @param url remote json file
- */
- public GeoJsonSource(String id, URL url) {
- initialize(id, null);
- nativeSetUrl(url.toExternalForm());
- }
-
- /**
- * Create a GeoJsonSource from a remote geo json file and non-default {@link GeoJsonOptions}
- *
- * @param id the source id
- * @param url remote json file
- * @param options options
- */
- public GeoJsonSource(String id, URL url, GeoJsonOptions options) {
- initialize(id, options);
- nativeSetUrl(url.toExternalForm());
- }
-
- /**
- * Create a GeoJsonSource from a {@link FeatureCollection}
- *
- * @param id the source id
- * @param features the features
- */
- public GeoJsonSource(String id, FeatureCollection features) {
- initialize(id, null);
- setGeoJson(features);
- }
-
- /**
- * Create a GeoJsonSource from a {@link FeatureCollection} and non-default {@link GeoJsonOptions}
- *
- * @param id the source id
- * @param features the features
- * @param options options
- */
- public GeoJsonSource(String id, FeatureCollection features, GeoJsonOptions options) {
- initialize(id, options);
- setGeoJson(features);
+ initialize(id, null);
+ setGeoJson(geoJson);
+ }
+
+ /**
+ * Create a GeoJsonSource from a raw json string and non-default {@link GeoJsonOptions}
+ *
+ * @param id the source id
+ * @param geoJson raw Json body
+ * @param options options
+ */
+ public GeoJsonSource(String id, String geoJson, GeoJsonOptions options) {
+ if (geoJson == null || geoJson.startsWith("http")) {
+ throw new IllegalArgumentException("Expected a raw json body");
}
-
- /**
- * Updates the GeoJson
- *
- * @param features the GeoJSON {@link FeatureCollection}
- */
- public void setGeoJson(FeatureCollection features) {
- checkValidity();
- setGeoJson(features.toJson());
- }
-
- /**
- * Updates the GeoJson
- *
- * @param json the raw GeoJson FeatureCollection string
- */
- public void setGeoJson(String json) {
- checkValidity();
- setRawJson(json);
- }
-
- /**
- * Updates the url
- *
- * @param url the GeoJSON FeatureCollection url
- */
- public void setUrl(URL url) {
- checkValidity();
- setUrl(url.toExternalForm());
- }
-
- /**
- * Updates the url
- *
- * @param url the GeoJSON FeatureCollection url
- */
- public void setUrl(String url) {
- checkValidity();
- nativeSetUrl(url);
- }
-
- protected void setRawJson(String geoJson) {
- //Wrap the String in a map as an Object is expected by the
- //style conversion template
- HashMap<String, String> wrapper = new HashMap<>();
- wrapper.put("data", geoJson);
- nativeSetGeoJson(wrapper);
- }
-
- protected native void initialize(String layerId, Object options);
-
- protected native void nativeSetUrl(String url);
-
- private native void nativeSetGeoJson(Object geoJson);
-
- @Override
- protected native void finalize() throws Throwable;
+ initialize(id, options);
+ setGeoJson(geoJson);
+ }
+
+ /**
+ * Create a GeoJsonSource from a remote geo json file
+ *
+ * @param id the source id
+ * @param url remote json file
+ */
+ public GeoJsonSource(String id, URL url) {
+ initialize(id, null);
+ nativeSetUrl(url.toExternalForm());
+ }
+
+ /**
+ * Create a GeoJsonSource from a remote geo json file and non-default {@link GeoJsonOptions}
+ *
+ * @param id the source id
+ * @param url remote json file
+ * @param options options
+ */
+ public GeoJsonSource(String id, URL url, GeoJsonOptions options) {
+ initialize(id, options);
+ nativeSetUrl(url.toExternalForm());
+ }
+
+ /**
+ * Create a GeoJsonSource from a {@link FeatureCollection}
+ *
+ * @param id the source id
+ * @param features the features
+ */
+ public GeoJsonSource(String id, FeatureCollection features) {
+ initialize(id, null);
+ setGeoJson(features);
+ }
+
+ /**
+ * Create a GeoJsonSource from a {@link FeatureCollection} and non-default {@link GeoJsonOptions}
+ *
+ * @param id the source id
+ * @param features the features
+ * @param options options
+ */
+ public GeoJsonSource(String id, FeatureCollection features, GeoJsonOptions options) {
+ initialize(id, options);
+ setGeoJson(features);
+ }
+
+ /**
+ * Updates the GeoJson
+ *
+ * @param features the GeoJSON {@link FeatureCollection}
+ */
+ public void setGeoJson(FeatureCollection features) {
+ checkValidity();
+ setGeoJson(features.toJson());
+ }
+
+ /**
+ * Updates the GeoJson
+ *
+ * @param json the raw GeoJson FeatureCollection string
+ */
+ public void setGeoJson(String json) {
+ checkValidity();
+ setRawJson(json);
+ }
+
+ /**
+ * Updates the url
+ *
+ * @param url the GeoJSON FeatureCollection url
+ */
+ public void setUrl(URL url) {
+ checkValidity();
+ setUrl(url.toExternalForm());
+ }
+
+ /**
+ * Updates the url
+ *
+ * @param url the GeoJSON FeatureCollection url
+ */
+ public void setUrl(String url) {
+ checkValidity();
+ nativeSetUrl(url);
+ }
+
+ protected void setRawJson(String geoJson) {
+ //Wrap the String in a map as an Object is expected by the
+ //style conversion template
+ HashMap<String, String> wrapper = new HashMap<>();
+ wrapper.put("data", geoJson);
+ nativeSetGeoJson(wrapper);
+ }
+
+ protected native void initialize(String layerId, Object options);
+
+ protected native void nativeSetUrl(String url);
+
+ private native void nativeSetGeoJson(Object geoJson);
+
+ @Override
+ protected native void finalize() throws Throwable;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/NoSuchSourceException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/NoSuchSourceException.java
index 4622d72445..06d35b598b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/NoSuchSourceException.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/NoSuchSourceException.java
@@ -5,7 +5,7 @@ package com.mapbox.mapboxsdk.style.sources;
*/
public class NoSuchSourceException extends Exception {
- public NoSuchSourceException(String message) {
- super(message);
- }
+ public NoSuchSourceException(String message) {
+ super(message);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java
index 7a7ae49909..eabbdb8395 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java
@@ -8,72 +8,72 @@ import java.net.URL;
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-raster">The style specification</a>
*/
public class RasterSource extends Source {
- public static final int DEFAULT_TILE_SIZE = 512;
+ public static final int DEFAULT_TILE_SIZE = 512;
- /**
- * Internal use
- *
- * @param nativePtr - pointer to native peer
- */
- public RasterSource(long nativePtr) {
- super(nativePtr);
- }
+ /**
+ * Internal use
+ *
+ * @param nativePtr - pointer to native peer
+ */
+ public RasterSource(long nativePtr) {
+ super(nativePtr);
+ }
- /**
- * Create the raster source from an URL
- *
- * @param id the source id
- * @param url the source url
- */
- public RasterSource(String id, URL url) {
- this(id, url.toExternalForm());
- }
+ /**
+ * Create the raster source from an URL
+ *
+ * @param id the source id
+ * @param url the source url
+ */
+ public RasterSource(String id, URL url) {
+ this(id, url.toExternalForm());
+ }
- /**
- * Create the raster source from an URL
- *
- * @param id the source id
- * @param url the source url
- */
- public RasterSource(String id, String url) {
- initialize(id, url, DEFAULT_TILE_SIZE);
- }
+ /**
+ * Create the raster source from an URL
+ *
+ * @param id the source id
+ * @param url the source url
+ */
+ public RasterSource(String id, String url) {
+ initialize(id, url, DEFAULT_TILE_SIZE);
+ }
- /**
- * Create the raster source from an URL with a specific tile size
- *
- * @param id the source id
- * @param url the source url
- * @param tileSize the tile size
- */
- public RasterSource(String id, String url, int tileSize) {
- initialize(id, url, tileSize);
- }
+ /**
+ * Create the raster source from an URL with a specific tile size
+ *
+ * @param id the source id
+ * @param url the source url
+ * @param tileSize the tile size
+ */
+ public RasterSource(String id, String url, int tileSize) {
+ initialize(id, url, tileSize);
+ }
- /**
- * Create the raster source from a {@link TileSet}
- *
- * @param id the source id
- * @param tileSet the {@link TileSet}
- */
- public RasterSource(String id, TileSet tileSet) {
- initialize(id, tileSet.toValueObject(), DEFAULT_TILE_SIZE);
- }
+ /**
+ * Create the raster source from a {@link TileSet}
+ *
+ * @param id the source id
+ * @param tileSet the {@link TileSet}
+ */
+ public RasterSource(String id, TileSet tileSet) {
+ initialize(id, tileSet.toValueObject(), DEFAULT_TILE_SIZE);
+ }
- /**
- * Create the raster source from a {@link TileSet} with a specific tile size
- *
- * @param id the source id
- * @param tileSet the {@link TileSet}
- * @param tileSize tje tile size
- */
- public RasterSource(String id, TileSet tileSet, int tileSize) {
- initialize(id, tileSet.toValueObject(), tileSize);
- }
+ /**
+ * Create the raster source from a {@link TileSet} with a specific tile size
+ *
+ * @param id the source id
+ * @param tileSet the {@link TileSet}
+ * @param tileSize tje tile size
+ */
+ public RasterSource(String id, TileSet tileSet, int tileSize) {
+ initialize(id, tileSet.toValueObject(), tileSize);
+ }
- protected native void initialize(String layerId, Object payload, int tileSize);
+ protected native void initialize(String layerId, Object payload, int tileSize);
- @Override
- protected native void finalize() throws Throwable;
+ @Override
+ protected native void finalize() throws Throwable;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java
index 0856b117dc..6826fed1b5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java
@@ -4,52 +4,52 @@ package com.mapbox.mapboxsdk.style.sources;
* Base Peer class for sources. see source.hpp for the other half of the peer.
*/
public abstract class Source {
- private long nativePtr;
- private boolean invalidated;
-
- /**
- * Internal use
- *
- * @param nativePtr - pointer to native peer
- */
- public Source(long nativePtr) {
- this.nativePtr = nativePtr;
- }
-
- public Source() {
- }
-
- /**
- * Retrieve the source id
- *
- * @return the source id
- */
- public String getId() {
- checkValidity();
- return nativeGetId();
- }
-
- /**
- * Internal use
- *
- * @return the native peer pointer
- */
- public long getNativePtr() {
- return nativePtr;
- }
-
- protected native String nativeGetId();
-
- protected void checkValidity() {
- if (invalidated) {
- throw new RuntimeException("Layer has been invalidated. Request a new reference after adding");
- }
- }
-
- /**
- * Internal use - invalidates the source for further use (after adding it to the map)
- */
- public final void invalidate() {
- this.invalidated = true;
+ private long nativePtr;
+ private boolean invalidated;
+
+ /**
+ * Internal use
+ *
+ * @param nativePtr - pointer to native peer
+ */
+ public Source(long nativePtr) {
+ this.nativePtr = nativePtr;
+ }
+
+ public Source() {
+ }
+
+ /**
+ * Retrieve the source id
+ *
+ * @return the source id
+ */
+ public String getId() {
+ checkValidity();
+ return nativeGetId();
+ }
+
+ /**
+ * Internal use
+ *
+ * @return the native peer pointer
+ */
+ public long getNativePtr() {
+ return nativePtr;
+ }
+
+ protected native String nativeGetId();
+
+ protected void checkValidity() {
+ if (invalidated) {
+ throw new RuntimeException("Layer has been invalidated. Request a new reference after adding");
}
+ }
+
+ /**
+ * Internal use - invalidates the source for further use (after adding it to the map)
+ */
+ public final void invalidate() {
+ this.invalidated = true;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java
index b645020c21..9f403c2fb9 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java
@@ -13,304 +13,307 @@ import java.util.Map;
* @see <a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">The tileset specification</a>
*/
public class TileSet {
- private final String tilejson;
- private String name;
- private String description;
- private String version;
- private String attribution;
- private String template;
- private String legend;
- private String scheme;
- private final String[] tiles;
- private String[] grids;
- private String[] data;
- private Float minZoom;
- private Float maxZoom;
- private Float[] bounds;
- private Float[] center;
-
- /**
- * @param tilejson A semver.org style version number. Describes the version of the TileJSON spec that is implemented by this JSON object.
- * @param tiles An array of tile endpoints. {z}, {x} and {y}, if present, are replaced with the corresponding integers.
- * If multiple endpoints are specified, clients may use any combination of endpoints. All endpoints MUST return the same
- * content for the same URL. The array MUST contain at least one endpoint.
- * Example: "http:localhost:8888/admin/1.0.0/world-light,broadband/{z}/{x}/{y}.png"
- */
- public TileSet(String tilejson, String... tiles) {
- this.tilejson = tilejson;
- this.tiles = tiles;
+ private final String tilejson;
+ private String name;
+ private String description;
+ private String version;
+ private String attribution;
+ private String template;
+ private String legend;
+ private String scheme;
+ private final String[] tiles;
+ private String[] grids;
+ private String[] data;
+ private Float minZoom;
+ private Float maxZoom;
+ private Float[] bounds;
+ private Float[] center;
+
+ /**
+ * @param tilejson A semver.org style version number. Describes the version of the TileJSON spec that is implemented
+ * by this JSON object.
+ * @param tiles An array of tile endpoints. {z}, {x} and {y}, if present, are replaced with the corresponding
+ * integers.
+ * If multiple endpoints are specified, clients may use any combination of endpoints. All endpoints
+ * MUST return the same
+ * content for the same URL. The array MUST contain at least one endpoint.
+ * Example: "http:localhost:8888/admin/1.0.0/world-light,broadband/{z}/{x}/{y}.png"
+ */
+ public TileSet(String tilejson, String... tiles) {
+ this.tilejson = tilejson;
+ this.tiles = tiles;
+ }
+
+ public String getTilejson() {
+ return tilejson;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * A name describing the tileset. The name can
+ * contain any legal character. Implementations SHOULD NOT interpret the
+ * name as HTML.
+ * "name": "compositing",
+ *
+ * @param name the name to be set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * A text description of the tileset. The
+ * description can contain any legal character.
+ * Implementations SHOULD NOT
+ * interpret the description as HTML.
+ * "description": "A simple, light grey world."
+ *
+ * @param description the description to set
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getAttribution() {
+ return attribution;
+ }
+
+ /**
+ * Default: null. Contains an attribution to be displayed
+ * when the map is shown to a user. Implementations MAY decide to treat this
+ * as HTML or literal text. For security reasons, make absolutely sure that
+ * this field can't be abused as a vector for XSS or beacon tracking.
+ * "attribution": "<a href='http:openstreetmap.org'>OSM contributors</a>",
+ *
+ * @param attribution the attribution to set
+ */
+ public void setAttribution(String attribution) {
+ this.attribution = attribution;
+ }
+
+ public String getTemplate() {
+ return template;
+ }
+
+ /**
+ * Contains a mustache template to be used to
+ * format data from grids for interaction.
+ * See https:github.com/mapbox/utfgrid-spec/tree/master/1.2
+ * for the interactivity specification.
+ * "template": "{{#__teaser__}}{{NAME}}{{/__teaser__}}"
+ *
+ * @param template the template to set
+ */
+ public void setTemplate(String template) {
+ this.template = template;
+ }
+
+ public String getLegend() {
+ return legend;
+ }
+
+ /**
+ * Contains a legend to be displayed with the map.
+ * Implementations MAY decide to treat this as HTML or literal text.
+ * For security reasons, make absolutely sure that this field can't be
+ * abused as a vector for XSS or beacon tracking.
+ * "legend": "Dangerous zones are red, safe zones are green"
+ *
+ * @param legend the legend to set
+ */
+ public void setLegend(String legend) {
+ this.legend = legend;
+ }
+
+ public String getScheme() {
+ return scheme;
+ }
+
+ /**
+ * Default: "xyz". Either "xyz" or "tms". Influences the y
+ * direction of the tile coordinates.
+ * The global-mercator (aka Spherical Mercator) profile is assumed.
+ * "scheme": "xyz"
+ *
+ * @param scheme the scheme to set
+ */
+ public void setScheme(String scheme) {
+ this.scheme = scheme;
+ }
+
+ public String[] getTiles() {
+ return tiles;
+ }
+
+ public String[] getGrids() {
+ return grids;
+ }
+
+ /**
+ * An array of interactivity endpoints. {z}, {x}
+ * and {y}, if present, are replaced with the corresponding integers. If multiple
+ * endpoints are specified, clients may use any combination of endpoints.
+ * All endpoints MUST return the same content for the same URL.
+ * If the array doesn't contain any entries, interactivity is not supported
+ * for this tileset. See https:github.com/mapbox/utfgrid-spec/tree/master/1.2
+ * for the interactivity specification.
+ * <p>
+ * Example: "http:localhost:8888/admin/1.0.0/broadband/{z}/{x}/{y}.grid.json"
+ * </p>
+ *
+ * @param grids the grids to set
+ */
+ public void setGrids(String... grids) {
+ this.grids = grids;
+ }
+
+ public String[] getData() {
+ return data;
+ }
+
+ /**
+ * An array of data files in GeoJSON format.
+ * {z}, {x} and {y}, if present,
+ * are replaced with the corresponding integers. If multiple
+ * endpoints are specified, clients may use any combination of endpoints.
+ * All endpoints MUST return the same content for the same URL.
+ * If the array doesn't contain any entries, then no data is present in
+ * the map.
+ * <p>
+ * "http:localhost:8888/admin/data.geojson"
+ * </p>
+ *
+ * @param data the data array to set
+ */
+ public void setData(String... data) {
+ this.data = data;
+ }
+
+ public float getMinZoom() {
+ return minZoom;
+ }
+
+ /**
+ * 0. &gt;= 0, &lt; 22. An integer specifying the minimum zoom level.
+ *
+ * @param minZoom the minZoom level to set
+ */
+ public void setMinZoom(float minZoom) {
+ this.minZoom = minZoom;
+ }
+
+ public float getMaxZoom() {
+ return maxZoom;
+ }
+
+ /**
+ * 0. &gt;= 0, &lt;= 22. An integer specifying the maximum zoom level.
+ *
+ * @param maxZoom the maxZoom level to set
+ */
+ public void setMaxZoom(float maxZoom) {
+ this.maxZoom = maxZoom;
+ }
+
+ public Float[] getBounds() {
+ return bounds;
+ }
+
+ /**
+ * Default: [-180, -90, 180, 90]. The maximum extent of available map tiles. Bounds MUST define an area
+ * covered by all zoom levels. The bounds are represented in WGS:84
+ * latitude and longitude values, in the order left, bottom, right, top.
+ * Values may be integers or floating point numbers.
+ *
+ * @param bounds the Float array to set
+ */
+ public void setBounds(@Size(value = 4) Float... bounds) {
+ this.bounds = bounds;
+ }
+
+ public Float[] getCenter() {
+ return center;
+ }
+
+ /**
+ * The first value is the longitude, the second is latitude (both in
+ * WGS:84 values), the third value is the zoom level as an integer.
+ * Longitude and latitude MUST be within the specified bounds.
+ * The zoom level MUST be between minzoom and maxzoom.
+ * Implementations can use this value to set the default location. If the
+ * value is null, implementations may use their own algorithm for
+ * determining a default location.
+ *
+ * @param center the Float array to set
+ */
+ public void setCenter(@Size(value = 2) Float... center) {
+ this.center = center;
+ }
+
+ public void setCenter(LatLng center) {
+ this.center = new Float[] {(float) center.getLongitude(), (float) center.getLatitude()};
+ }
+
+ Map<String, Object> toValueObject() {
+ Map<String, Object> result = new HashMap<>();
+ result.put("tilejson", tilejson);
+ result.put("tiles", tiles);
+
+ if (name != null) {
+ result.put("name", name);
}
-
- public String getTilejson() {
- return tilejson;
- }
-
- public String getName() {
- return name;
- }
-
- /**
- * A name describing the tileset. The name can
- * contain any legal character. Implementations SHOULD NOT interpret the
- * name as HTML.
- * "name": "compositing",
- *
- * @param name the name to be set
- */
- public void setName(String name) {
- this.name = name;
- }
-
- public String getDescription() {
- return description;
- }
-
- /**
- * A text description of the tileset. The
- * description can contain any legal character.
- * Implementations SHOULD NOT
- * interpret the description as HTML.
- * "description": "A simple, light grey world."
- *
- * @param description the description to set
- */
- public void setDescription(String description) {
- this.description = description;
- }
-
- public String getVersion() {
- return version;
- }
-
- public void setVersion(String version) {
- this.version = version;
+ if (description != null) {
+ result.put("description", description);
}
-
- public String getAttribution() {
- return attribution;
+ if (version != null) {
+ result.put("version", version);
}
-
- /**
- * Default: null. Contains an attribution to be displayed
- * when the map is shown to a user. Implementations MAY decide to treat this
- * as HTML or literal text. For security reasons, make absolutely sure that
- * this field can't be abused as a vector for XSS or beacon tracking.
- * "attribution": "<a href='http:openstreetmap.org'>OSM contributors</a>",
- *
- * @param attribution the attribution to set
- */
- public void setAttribution(String attribution) {
- this.attribution = attribution;
+ if (attribution != null) {
+ result.put("attribution", attribution);
}
-
- public String getTemplate() {
- return template;
+ if (template != null) {
+ result.put("template", template);
}
-
- /**
- * Contains a mustache template to be used to
- * format data from grids for interaction.
- * See https:github.com/mapbox/utfgrid-spec/tree/master/1.2
- * for the interactivity specification.
- * "template": "{{#__teaser__}}{{NAME}}{{/__teaser__}}"
- *
- * @param template the template to set
- */
- public void setTemplate(String template) {
- this.template = template;
+ if (legend != null) {
+ result.put("legend", legend);
}
-
- public String getLegend() {
- return legend;
+ if (scheme != null) {
+ result.put("scheme", scheme);
}
-
- /**
- * Contains a legend to be displayed with the map.
- * Implementations MAY decide to treat this as HTML or literal text.
- * For security reasons, make absolutely sure that this field can't be
- * abused as a vector for XSS or beacon tracking.
- * "legend": "Dangerous zones are red, safe zones are green"
- *
- * @param legend the legend to set
- */
- public void setLegend(String legend) {
- this.legend = legend;
+ if (grids != null) {
+ result.put("grids", grids);
}
-
- public String getScheme() {
- return scheme;
+ if (data != null) {
+ result.put("data", data);
}
-
- /**
- * Default: "xyz". Either "xyz" or "tms". Influences the y
- * direction of the tile coordinates.
- * The global-mercator (aka Spherical Mercator) profile is assumed.
- * "scheme": "xyz"
- *
- * @param scheme the scheme to set
- */
- public void setScheme(String scheme) {
- this.scheme = scheme;
+ if (minZoom != null) {
+ result.put("minzoom", minZoom);
}
-
- public String[] getTiles() {
- return tiles;
+ if (maxZoom != null) {
+ result.put("maxzoom", maxZoom);
}
-
- public String[] getGrids() {
- return grids;
+ if (bounds != null) {
+ result.put("bounds", bounds);
}
-
- /**
- * An array of interactivity endpoints. {z}, {x}
- * and {y}, if present, are replaced with the corresponding integers. If multiple
- * endpoints are specified, clients may use any combination of endpoints.
- * All endpoints MUST return the same content for the same URL.
- * If the array doesn't contain any entries, interactivity is not supported
- * for this tileset. See https:github.com/mapbox/utfgrid-spec/tree/master/1.2
- * for the interactivity specification.
- * <p>
- * Example: "http:localhost:8888/admin/1.0.0/broadband/{z}/{x}/{y}.grid.json"
- * </p>
- *
- * @param grids the grids to set
- */
- public void setGrids(String... grids) {
- this.grids = grids;
+ if (center != null) {
+ result.put("center", center);
}
- public String[] getData() {
- return data;
- }
-
- /**
- * An array of data files in GeoJSON format.
- * {z}, {x} and {y}, if present,
- * are replaced with the corresponding integers. If multiple
- * endpoints are specified, clients may use any combination of endpoints.
- * All endpoints MUST return the same content for the same URL.
- * If the array doesn't contain any entries, then no data is present in
- * the map.
- * <p>
- * "http:localhost:8888/admin/data.geojson"
- * </p>
- *
- * @param data the data array to set
- */
- public void setData(String... data) {
- this.data = data;
- }
-
- public float getMinZoom() {
- return minZoom;
- }
-
- /**
- * 0. &gt;= 0, &lt; 22. An integer specifying the minimum zoom level.
- *
- * @param minZoom the minZoom level to set
- */
- public void setMinZoom(float minZoom) {
- this.minZoom = minZoom;
- }
-
- public float getMaxZoom() {
- return maxZoom;
- }
-
- /**
- * 0. &gt;= 0, &lt;= 22. An integer specifying the maximum zoom level.
- *
- * @param maxZoom the maxZoom level to set
- */
- public void setMaxZoom(float maxZoom) {
- this.maxZoom = maxZoom;
- }
-
- public Float[] getBounds() {
- return bounds;
- }
-
- /**
- * Default: [-180, -90, 180, 90]. The maximum extent of available map tiles. Bounds MUST define an area
- * covered by all zoom levels. The bounds are represented in WGS:84
- * latitude and longitude values, in the order left, bottom, right, top.
- * Values may be integers or floating point numbers.
- *
- * @param bounds the Float array to set
- */
- public void setBounds(@Size(value = 4) Float... bounds) {
- this.bounds = bounds;
- }
-
- public Float[] getCenter() {
- return center;
- }
-
- /**
- * The first value is the longitude, the second is latitude (both in
- * WGS:84 values), the third value is the zoom level as an integer.
- * Longitude and latitude MUST be within the specified bounds.
- * The zoom level MUST be between minzoom and maxzoom.
- * Implementations can use this value to set the default location. If the
- * value is null, implementations may use their own algorithm for
- * determining a default location.
- *
- * @param center the Float array to set
- */
- public void setCenter(@Size(value = 2) Float... center) {
- this.center = center;
- }
-
- public void setCenter(LatLng center) {
- this.center = new Float[]{(float) center.getLongitude(), (float) center.getLatitude()};
- }
-
- Map<String, Object> toValueObject() {
- Map<String, Object> result = new HashMap<>();
- result.put("tilejson", tilejson);
- result.put("tiles", tiles);
-
- if (name != null) {
- result.put("name", name);
- }
- if (description != null) {
- result.put("description", description);
- }
- if (version != null) {
- result.put("version", version);
- }
- if (attribution != null) {
- result.put("attribution", attribution);
- }
- if (template != null) {
- result.put("template", template);
- }
- if (legend != null) {
- result.put("legend", legend);
- }
- if (scheme != null) {
- result.put("scheme", scheme);
- }
- if (grids != null) {
- result.put("grids", grids);
- }
- if (data != null) {
- result.put("data", data);
- }
- if (minZoom != null) {
- result.put("minzoom", minZoom);
- }
- if (maxZoom != null) {
- result.put("maxzoom", maxZoom);
- }
- if (bounds != null) {
- result.put("bounds", bounds);
- }
- if (center != null) {
- result.put("center", center);
- }
-
- return result;
- }
+ return result;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java
index 689ea7c6bc..feaca839d3 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java
@@ -9,47 +9,47 @@ import java.net.URL;
*/
public class VectorSource extends Source {
- /**
- * Internal use
- *
- * @param nativePtr - pointer to native peer
- */
- public VectorSource(long nativePtr) {
- super(nativePtr);
- }
-
- /**
- * Create a vector source from a remote url
- *
- * @param id the source id
- * @param url the url
- */
- public VectorSource(String id, URL url) {
- this(id, url.toExternalForm());
- }
-
- /**
- * Create a vector source from a remote url
- *
- * @param id the source id
- * @param url the url
- */
- public VectorSource(String id, String url) {
- initialize(id, url);
- }
-
- /**
- * Create a vector source from a tilset
- *
- * @param id the source id
- * @param tileSet the tileset
- */
- public VectorSource(String id, TileSet tileSet) {
- initialize(id, tileSet.toValueObject());
- }
-
- protected native void initialize(String layerId, Object payload);
-
- @Override
- protected native void finalize() throws Throwable;
+ /**
+ * Internal use
+ *
+ * @param nativePtr - pointer to native peer
+ */
+ public VectorSource(long nativePtr) {
+ super(nativePtr);
+ }
+
+ /**
+ * Create a vector source from a remote url
+ *
+ * @param id the source id
+ * @param url the url
+ */
+ public VectorSource(String id, URL url) {
+ this(id, url.toExternalForm());
+ }
+
+ /**
+ * Create a vector source from a remote url
+ *
+ * @param id the source id
+ * @param url the url
+ */
+ public VectorSource(String id, String url) {
+ initialize(id, url);
+ }
+
+ /**
+ * Create a vector source from a tilset
+ *
+ * @param id the source id
+ * @param tileSet the tileset
+ */
+ public VectorSource(String id, TileSet tileSet) {
+ initialize(id, tileSet.toValueObject());
+ }
+
+ protected native void initialize(String layerId, Object payload);
+
+ @Override
+ protected native void finalize() throws Throwable;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/GzipRequestInterceptor.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/GzipRequestInterceptor.java
index 1b13e9502f..8457d24ff2 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/GzipRequestInterceptor.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/GzipRequestInterceptor.java
@@ -1,7 +1,9 @@
package com.mapbox.mapboxsdk.telemetry;
-import android.util.Log;
+import timber.log.Timber;
+
import java.io.IOException;
+
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
@@ -17,38 +19,40 @@ import okio.Okio;
*/
public final class GzipRequestInterceptor implements Interceptor {
- private static final String TAG = "GzipRequestInterceptor";
-
- @Override public Response intercept(Interceptor.Chain chain) throws IOException {
- Request originalRequest = chain.request();
- if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
- Log.d(TAG, "Not compressing");
- return chain.proceed(originalRequest);
- }
-
- Log.d(TAG, "Compressing");
- Request compressedRequest = originalRequest.newBuilder()
- .header("Content-Encoding", "gzip")
- .method(originalRequest.method(), gzip(originalRequest.body()))
- .build();
- return chain.proceed(compressedRequest);
+ @Override
+ public Response intercept(Interceptor.Chain chain) throws IOException {
+ Request originalRequest = chain.request();
+ if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
+ Timber.d("Not compressing");
+ return chain.proceed(originalRequest);
}
- private RequestBody gzip(final RequestBody body) {
- return new RequestBody() {
- @Override public MediaType contentType() {
- return body.contentType();
- }
-
- @Override public long contentLength() {
- return -1; // We don't know the compressed length in advance!
- }
-
- @Override public void writeTo(BufferedSink sink) throws IOException {
- BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
- body.writeTo(gzipSink);
- gzipSink.close();
- }
- };
- }
+ Timber.d("Compressing");
+ Request compressedRequest = originalRequest.newBuilder()
+ .header("Content-Encoding", "gzip")
+ .method(originalRequest.method(), gzip(originalRequest.body()))
+ .build();
+ return chain.proceed(compressedRequest);
+ }
+
+ private RequestBody gzip(final RequestBody body) {
+ return new RequestBody() {
+ @Override
+ public MediaType contentType() {
+ return body.contentType();
+ }
+
+ @Override
+ public long contentLength() {
+ return -1; // We don't know the compressed length in advance!
+ }
+
+ @Override
+ public void writeTo(BufferedSink sink) throws IOException {
+ BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
+ body.writeTo(gzipSink);
+ gzipSink.close();
+ }
+ };
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java
index 22e37ec539..b5203bc02a 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java
@@ -1,66 +1,161 @@
package com.mapbox.mapboxsdk.telemetry;
+import android.graphics.PointF;
+import android.support.annotation.NonNull;
+
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.Projection;
+
import java.io.Serializable;
+import java.util.Hashtable;
+
+import timber.log.Timber;
/**
* Constants for Telemetry Metadata
*/
public class MapboxEvent implements Serializable {
- public static final int VERSION_NUMBER = 2;
- public static final String MAPBOX_EVENTS_BASE_URL = "https://events.mapbox.com";
- public static final String SOURCE_MAPBOX = "mapbox";
-
- // Event Types
- public static final String TYPE_TURNSTILE = "appUserTurnstile";
- public static final String TYPE_MAP_LOAD = "map.load";
- public static final String TYPE_MAP_CLICK = "map.click";
- public static final String TYPE_MAP_DRAGEND = "map.dragend";
- public static final String TYPE_LOCATION = "location";
- public static final String TYPE_VISIT = "visit";
-
- // Event Keys
- public static final String KEY_LATITUDE = "lat";
- public static final String KEY_LONGITUDE = "lng";
- public static final String KEY_SPEED = "speed";
- public static final String KEY_COURSE = "course";
- public static final String KEY_ALTITUDE = "altitude";
- public static final String KEY_HORIZONTAL_ACCURACY = "horizontalAccuracy";
- public static final String KEY_ZOOM = "zoom";
-
- public static final String KEY_PUSH_ENABLED = "enabled.push";
- public static final String KEY_EMAIL_ENABLED = "enabled.email";
- public static final String KEY_GESTURE_ID = "gesture";
- public static final String KEY_ARRIVAL_DATE = "arrivalDate";
- public static final String KEY_DEPARTURE_DATE = "departureDate";
-
- public static final String GESTURE_SINGLETAP = "SingleTap";
- public static final String GESTURE_DOUBLETAP = "DoubleTap";
- public static final String GESTURE_TWO_FINGER_SINGLETAP = "TwoFingerTap";
- public static final String GESTURE_QUICK_ZOOM = "QuickZoom";
- public static final String GESTURE_PAN_START = "Pan";
- public static final String GESTURE_PINCH_START = "Pinch";
- public static final String GESTURE_ROTATION_START = "Rotation";
- public static final String GESTURE_PITCH_START = "Pitch";
-
- // Event Attributes
- public static final String ATTRIBUTE_EVENT = "event";
- public static final String ATTRIBUTE_USERID = "userId";
- public static final String ATTRIBUTE_SOURCE = "source";
- public static final String ATTRIBUTE_ENABLED_TELEMETRY = "enabled.telemetry";
- public static final String ATTRIBUTE_SESSION_ID = "sessionId";
- public static final String ATTRIBUTE_VERSION = "version";
- public static final String ATTRIBUTE_CREATED = "created";
- public static final String ATTRIBUTE_VENDOR_ID = "vendorId";
- public static final String ATTRIBUTE_APP_BUNDLE_ID = "appBundleId";
- public static final String ATTRIBUTE_MODEL = "model";
- public static final String ATTRIBUTE_OPERATING_SYSTEM= "operatingSystem";
- public static final String ATTRIBUTE_ORIENTATION = "orientation";
- public static final String ATTRIBUTE_BATTERY_LEVEL = "batteryLevel";
- public static final String ATTRIBUTE_PLUGGED_IN = "pluggedIn";
- public static final String ATTRIBUTE_APPLICATION_STATE = "applicationState";
- public static final String ATTRIBUTE_RESOLUTION = "resolution";
- public static final String ATTRIBUTE_ACCESSIBILITY_FONT_SCALE = "accessibilityFontScale";
- public static final String ATTRIBUTE_CARRIER = "carrier";
- public static final String ATTRIBUTE_CELLULAR_NETWORK_TYPE = "cellularNetworkType";
- public static final String ATTRIBUTE_WIFI = "wifi";
+ public static final int VERSION_NUMBER = 2;
+ public static final String MAPBOX_EVENTS_BASE_URL = "https://events.mapbox.com";
+ public static final String SOURCE_MAPBOX = "mapbox";
+
+ // Event Types
+ public static final String TYPE_TURNSTILE = "appUserTurnstile";
+ public static final String TYPE_MAP_LOAD = "map.load";
+ public static final String TYPE_MAP_CLICK = "map.click";
+ public static final String TYPE_MAP_DRAGEND = "map.dragend";
+ public static final String TYPE_LOCATION = "location";
+ public static final String TYPE_VISIT = "visit";
+
+ // Event Keys
+ public static final String KEY_LATITUDE = "lat";
+ public static final String KEY_LONGITUDE = "lng";
+ public static final String KEY_SPEED = "speed";
+ public static final String KEY_COURSE = "course";
+ public static final String KEY_ALTITUDE = "altitude";
+ public static final String KEY_HORIZONTAL_ACCURACY = "horizontalAccuracy";
+ public static final String KEY_ZOOM = "zoom";
+
+ public static final String KEY_PUSH_ENABLED = "enabled.push";
+ public static final String KEY_EMAIL_ENABLED = "enabled.email";
+ public static final String KEY_GESTURE_ID = "gesture";
+ public static final String KEY_ARRIVAL_DATE = "arrivalDate";
+ public static final String KEY_DEPARTURE_DATE = "departureDate";
+
+ public static final String GESTURE_SINGLETAP = "SingleTap";
+ public static final String GESTURE_DOUBLETAP = "DoubleTap";
+ public static final String GESTURE_TWO_FINGER_SINGLETAP = "TwoFingerTap";
+ public static final String GESTURE_QUICK_ZOOM = "QuickZoom";
+ public static final String GESTURE_PAN_START = "Pan";
+ public static final String GESTURE_PINCH_START = "Pinch";
+ public static final String GESTURE_ROTATION_START = "Rotation";
+ public static final String GESTURE_PITCH_START = "Pitch";
+
+ // Event Attributes
+ public static final String ATTRIBUTE_EVENT = "event";
+ public static final String ATTRIBUTE_USERID = "userId";
+ public static final String ATTRIBUTE_SOURCE = "source";
+ public static final String ATTRIBUTE_ENABLED_TELEMETRY = "enabled.telemetry";
+ public static final String ATTRIBUTE_SESSION_ID = "sessionId";
+ public static final String ATTRIBUTE_VERSION = "version";
+ public static final String ATTRIBUTE_CREATED = "created";
+ public static final String ATTRIBUTE_VENDOR_ID = "vendorId";
+ public static final String ATTRIBUTE_APP_BUNDLE_ID = "appBundleId";
+ public static final String ATTRIBUTE_MODEL = "model";
+ public static final String ATTRIBUTE_OPERATING_SYSTEM = "operatingSystem";
+ public static final String ATTRIBUTE_ORIENTATION = "orientation";
+ public static final String ATTRIBUTE_BATTERY_LEVEL = "batteryLevel";
+ public static final String ATTRIBUTE_PLUGGED_IN = "pluggedIn";
+ public static final String ATTRIBUTE_APPLICATION_STATE = "applicationState";
+ public static final String ATTRIBUTE_RESOLUTION = "resolution";
+ public static final String ATTRIBUTE_ACCESSIBILITY_FONT_SCALE = "accessibilityFontScale";
+ public static final String ATTRIBUTE_CARRIER = "carrier";
+ public static final String ATTRIBUTE_CELLULAR_NETWORK_TYPE = "cellularNetworkType";
+ public static final String ATTRIBUTE_WIFI = "wifi";
+
+ /**
+ * Helper method for tracking gesture events
+ *
+ * @param projection Projection of the Map object
+ * @param gestureId Type of Gesture See {@see MapboxEvent#GESTURE_SINGLETAP
+ * MapboxEvent#GESTURE_DOUBLETAP
+ * MapboxEvent#GESTURE_TWO_FINGER_SINGLETAP
+ * MapboxEvent#GESTURE_QUICK_ZOOM
+ * MapboxEvent#GESTURE_PAN_START
+ * MapboxEvent#GESTURE_PINCH_START
+ * MapboxEvent#GESTURE_ROTATION_START
+ * MapboxEvent#GESTURE_PITCH_START}
+ * @param xCoordinate Original x screen coordinate at start of gesture
+ * @param yCoordinate Original y screen cooridnate at start of gesture
+ * @param zoom Zoom level to be registered
+ */
+ public static void trackGestureEvent(@NonNull Projection projection, @NonNull String gestureId, float xCoordinate,
+ float yCoordinate, double zoom) {
+ LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate));
+
+ // NaN and Infinite checks to prevent JSON errors at send to server time
+ if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) {
+ Timber.d("trackGestureEvent() has a NaN lat or lon. Returning.");
+ return;
+ }
+
+ if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) {
+ Timber.d("trackGestureEvent() has an Infinite lat or lon. Returning.");
+ return;
+ }
+
+ Hashtable<String, Object> evt = new Hashtable<>();
+ evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_CLICK);
+ evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate());
+ evt.put(MapboxEvent.KEY_GESTURE_ID, gestureId);
+ evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude());
+ evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude());
+ evt.put(MapboxEvent.KEY_ZOOM, zoom);
+
+ MapboxEventManager.getMapboxEventManager().pushEvent(evt);
+ }
+
+ /**
+ * Helper method for tracking DragEnd gesture event
+ * See {@see MapboxEvent#TYPE_MAP_DRAGEND}
+ *
+ * @param projection projection of the Map object.
+ * @param xCoordinate Original x screen coordinate at end of drag
+ * @param yCoordinate Orginal y screen coordinate at end of drag
+ * @param zoom Zoom level to be registered
+ */
+ public static void trackGestureDragEndEvent(@NonNull Projection projection, float xCoordinate, float yCoordinate,
+ double zoom) {
+ LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate));
+
+ // NaN and Infinite checks to prevent JSON errors at send to server time
+ if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) {
+ Timber.d("trackGestureDragEndEvent() has a NaN lat or lon. Returning.");
+ return;
+ }
+
+ if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) {
+ Timber.d("trackGestureDragEndEvent() has an Infinite lat or lon. Returning.");
+ return;
+ }
+
+ Hashtable<String, Object> evt = new Hashtable<>();
+ evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_DRAGEND);
+ evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate());
+ evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude());
+ evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude());
+ evt.put(MapboxEvent.KEY_ZOOM, zoom);
+
+ MapboxEventManager.getMapboxEventManager().pushEvent(evt);
+ }
+
+ /**
+ * Helper method for tracking map load event
+ */
+ public static void trackMapLoadEvent() {
+ Hashtable<String, Object> evt = new Hashtable<>();
+ evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_LOAD);
+ evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate());
+ MapboxEventManager.getMapboxEventManager().pushEvent(evt);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java
index bedb54ca46..4a0ef248b7 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java
@@ -21,11 +21,10 @@ import android.support.annotation.NonNull;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
-import android.util.Log;
import android.view.WindowManager;
import com.mapbox.mapboxsdk.BuildConfig;
-import com.mapbox.mapboxsdk.MapboxAccountManager;
+import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.constants.GeoConstants;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.exceptions.TelemetryServiceNotConfiguredException;
@@ -53,6 +52,7 @@ import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.internal.Util;
+import timber.log.Timber;
/**
* Singleton control center for managing Telemetry Data.
@@ -60,733 +60,769 @@ import okhttp3.internal.Util;
*/
public class MapboxEventManager {
- private static final String TAG = "MapboxEventManager";
+ private static MapboxEventManager mapboxEventManager = null;
- private static MapboxEventManager mapboxEventManager = null;
+ private boolean initialized = false;
+ private boolean stagingEnv;
+ private boolean telemetryEnabled;
- private boolean initialized = false;
- private boolean stagingEnv;
- private boolean telemetryEnabled;
+ private final Vector<Hashtable<String, Object>> events = new Vector<>();
+ private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
+ private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ",
+ MapboxConstants.MAPBOX_LOCALE);
- private final Vector<Hashtable<String, Object>> events = new Vector<>();
- private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
- private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", MapboxConstants.MAPBOX_LOCALE);
+ private Context context = null;
+ private String accessToken = null;
+ private String eventsURL = MapboxEvent.MAPBOX_EVENTS_BASE_URL;
- private Context context = null;
- private String accessToken = null;
- private String eventsURL = MapboxEvent.MAPBOX_EVENTS_BASE_URL;
+ private String userAgent = BuildConfig.MAPBOX_EVENTS_USER_AGENT_BASE;
- private String userAgent = BuildConfig.MAPBOX_EVENTS_USER_AGENT_BASE;
+ private Intent batteryStatus = null;
+ private final String operatingSystem = "Android - " + Build.VERSION.RELEASE;
- private Intent batteryStatus = null;
- private final String operatingSystem = "Android - " + Build.VERSION.RELEASE;
+ private DisplayMetrics displayMetrics = null;
- private DisplayMetrics displayMetrics = null;
+ private String mapboxVendorId = null;
- private String mapboxVendorId = null;
+ private String mapboxSessionId = null;
+ private long mapboxSessionIdLastSet = 0;
+ private static long hourInMillis = 1000 * 60 * 60;
+ private static long flushDelayInitialInMillis = 1000 * 10; // 10 Seconds
+ private static long flushDelayInMillis = 1000 * 60 * 3; // 3 Minutes
+ private static final int SESSION_ID_ROTATION_HOURS = 24;
- private String mapboxSessionId = null;
- private long mapboxSessionIdLastSet = 0;
- private static long hourInMillis = 1000 * 60 * 60;
- private static long flushDelayInitialInMillis = 1000 * 10; // 10 Seconds
- private static long flushDelayInMillis = 1000 * 60 * 3; // 3 Minutes
- private static final int SESSION_ID_ROTATION_HOURS = 24;
+ private static final int FLUSH_EVENTS_CAP = 1000;
- private static final int FLUSH_EVENTS_CAP = 1000;
+ private static MessageDigest messageDigest = null;
- private static MessageDigest messageDigest = null;
+ private static final double locationEventAccuracy = 10000000;
- private static final double locationEventAccuracy = 10000000;
+ private Timer timer = null;
- private Timer timer = null;
+ /**
+ * Private Constructor for configuring the single instance per app.
+ */
+ private MapboxEventManager() {
+ super();
+ }
- /**
- * Private Constructor for configuring the single instance per app.
- */
- private MapboxEventManager() {
- super();
- }
-
- /**
- * Internal setup of MapboxEventsManager. It needs to be called once before @link MapboxEventManager#getMapboxEventManager
- *
- * This allows for a cleaner getMapboxEventManager() that doesn't require context and accessToken
- *
- * @param context The context associated with MapView
- * @param accessToken The accessToken to load MapView
- */
- public void initialize(@NonNull Context context, @NonNull String accessToken) {
-
- Log.i(TAG, "Telemetry initialize() called...");
-
- if (initialized) {
- Log.i(TAG, "Mapbox Telemetry has already been initialized.");
- return;
- }
-
- this.context = context.getApplicationContext();
- this.accessToken = accessToken;
-
- validateTelemetryServiceConfigured();
-
- // Setup Message Digest
- try {
- messageDigest = MessageDigest.getInstance("SHA-1");
- } catch (NoSuchAlgorithmException e) {
- Log.w(TAG, "Error getting Encryption Algorithm: " + e);
- }
-
- // Create Initial Session Id
- rotateSessionId();
-
- SharedPreferences prefs = context.getSharedPreferences(MapboxConstants.MAPBOX_SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE);
+ /**
+ * Internal setup of MapboxEventsManager. It needs to be called once before @link
+ * MapboxEventManager#getMapboxEventManager
+ * <p>
+ * This allows for a cleaner getMapboxEventManager() that doesn't require context and accessToken
+ *
+ * @param context The context associated with MapView
+ * @param accessToken The accessToken to load MapView
+ */
+ public void initialize(@NonNull Context context, @NonNull String accessToken) {
- // Determine if Telemetry Should Be Enabled
- Log.i(TAG, "Right before Telemetry set enabled in initialized()");
- setTelemetryEnabled(prefs.getBoolean(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED, true));
+ //Timber.i("Telemetry initialize() called...");
- // Load / Create Vendor Id
- if (prefs.contains(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID)) {
- mapboxVendorId = prefs.getString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID, "");
- }
- if (TextUtils.isEmpty(mapboxVendorId)) {
- String vendorId = UUID.randomUUID().toString();
- mapboxVendorId = encodeString(vendorId);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID, mapboxVendorId);
- editor.apply();
- editor.commit();
- }
-
- // Get DisplayMetrics Setup
- displayMetrics = new DisplayMetrics();
- ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics);
+ if (initialized) {
+ //Timber.i("Mapbox Telemetry has already been initialized.");
+ return;
+ }
- // Check for Staging Server Information
- try {
- ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
- String stagingURL = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_STAGING_SERVER);
- String stagingAccessToken = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_STAGING_ACCESS_TOKEN);
+ this.context = context.getApplicationContext();
+ this.accessToken = accessToken;
- if (TextUtils.isEmpty(stagingURL) || TextUtils.isEmpty(stagingAccessToken)) {
- Log.d(TAG, "Looking in SharedPreferences for Staging Credentials");
- stagingURL = prefs.getString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_URL, null);
- stagingAccessToken = prefs.getString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_ACCESS_TOKEN, null);
- }
+ validateTelemetryServiceConfigured();
- if (!TextUtils.isEmpty(stagingURL) && !TextUtils.isEmpty(stagingAccessToken)) {
- eventsURL = stagingURL;
- this.accessToken = accessToken;
- stagingEnv = true;
- }
+ // Setup Message Digest
+ try {
+ messageDigest = MessageDigest.getInstance("SHA-1");
+ } catch (NoSuchAlgorithmException exception) {
+ Timber.w("Error getting Encryption Algorithm: ", exception);
+ }
- // Build User Agent
- String appIdentifier = getApplicationIdentifier();
- if (TextUtils.equals(userAgent, BuildConfig.MAPBOX_EVENTS_USER_AGENT_BASE) && !TextUtils.isEmpty(appIdentifier)) {
- userAgent = Util.toHumanReadableAscii(String.format(MapboxConstants.MAPBOX_LOCALE, "%s %s", appIdentifier, userAgent));
- }
+ // Create Initial Session Id
+ rotateSessionId();
- } catch (Exception e) {
- Log.e(TAG, "Error Trying to load Staging Credentials: " + e.toString());
- }
+ SharedPreferences prefs = context.getSharedPreferences(MapboxConstants.MAPBOX_SHARED_PREFERENCES_FILE,
+ Context.MODE_PRIVATE);
- // Register for battery updates
- IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
- batteryStatus = context.registerReceiver(null, iFilter);
+ // Determine if Telemetry Should Be Enabled
+ ///Timber.i("Right before Telemetry set enabled in initialized()");
+ setTelemetryEnabled(prefs.getBoolean(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED, true));
- initialized = true;
+ // Load / Create Vendor Id
+ if (prefs.contains(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID)) {
+ mapboxVendorId = prefs.getString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID, "");
+ }
+ if (TextUtils.isEmpty(mapboxVendorId)) {
+ String vendorId = UUID.randomUUID().toString();
+ mapboxVendorId = encodeString(vendorId);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID, mapboxVendorId);
+ editor.apply();
+ editor.commit();
}
- /**
- * Primary Access method using Singleton pattern
- *
- * @return MapboxEventManager
- */
- public static MapboxEventManager getMapboxEventManager() {
- if (mapboxEventManager == null) {
- mapboxEventManager = new MapboxEventManager();
- }
- return mapboxEventManager;
+ // Get DisplayMetrics Setup
+ displayMetrics = new DisplayMetrics();
+ ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics);
+
+ // Check for Staging Server Information
+ try {
+ ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(),
+ PackageManager.GET_META_DATA);
+ String stagingURL = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_STAGING_SERVER);
+ String stagingAccessToken = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_STAGING_ACCESS_TOKEN);
+
+ if (TextUtils.isEmpty(stagingURL) || TextUtils.isEmpty(stagingAccessToken)) {
+ //Timber.d("Looking in SharedPreferences for Staging Credentials");
+ stagingURL = prefs.getString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_URL, null);
+ stagingAccessToken = prefs.getString(
+ MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_ACCESS_TOKEN, null);
+ }
+
+ if (!TextUtils.isEmpty(stagingURL) && !TextUtils.isEmpty(stagingAccessToken)) {
+ eventsURL = stagingURL;
+ this.accessToken = accessToken;
+ stagingEnv = true;
+ }
+
+ // Build User Agent
+ String appIdentifier = getApplicationIdentifier();
+ if (TextUtils.equals(userAgent, BuildConfig.MAPBOX_EVENTS_USER_AGENT_BASE) && !TextUtils.isEmpty(appIdentifier)) {
+ userAgent = Util
+ .toHumanReadableAscii(String.format(MapboxConstants.MAPBOX_LOCALE, "%s %s", appIdentifier, userAgent));
+ }
+
+ } catch (Exception exception) {
+ //Timber.e("Error Trying to load Staging Credentials: ", exception);
}
- // Checks that TelemetryService has been configured by developer
- private void validateTelemetryServiceConfigured() {
- try {
- // Check Implementing app's AndroidManifest.xml
- PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SERVICES);
- if (packageInfo.services != null) {
- for (ServiceInfo service : packageInfo.services) {
- if (TextUtils.equals("com.mapbox.mapboxsdk.telemetry.TelemetryService", service.name)) {
- return;
- }
- }
- }
- } catch (Exception e) {
- Log.w(MapboxConstants.TAG, "Error checking for Telemetry Service Config: " + e);
+ // Register for battery updates
+ IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+ batteryStatus = context.registerReceiver(null, iFilter);
+
+ initialized = true;
+ }
+
+ /**
+ * Primary Access method using Singleton pattern
+ *
+ * @return MapboxEventManager
+ */
+ public static MapboxEventManager getMapboxEventManager() {
+ if (mapboxEventManager == null) {
+ mapboxEventManager = new MapboxEventManager();
+ }
+ return mapboxEventManager;
+ }
+
+ // Checks that TelemetryService has been configured by developer
+ private void validateTelemetryServiceConfigured() {
+ try {
+ // Check Implementing app's AndroidManifest.xml
+ PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(),
+ PackageManager.GET_SERVICES);
+ if (packageInfo.services != null) {
+ for (ServiceInfo service : packageInfo.services) {
+ if (TextUtils.equals("com.mapbox.mapboxsdk.telemetry.TelemetryService", service.name)) {
+ return;
+ }
}
- throw new TelemetryServiceNotConfiguredException();
+ }
+ } catch (Exception exception) {
+ //Timber.w("Error checking for Telemetry Service Config: ", exception);
}
-
- public static String generateCreateDate() {
- return dateFormat.format(new Date());
+ throw new TelemetryServiceNotConfiguredException();
+ }
+
+ public static String generateCreateDate() {
+ return dateFormat.format(new Date());
+ }
+
+ public boolean isTelemetryEnabled() {
+ return telemetryEnabled;
+ }
+
+ /**
+ * Enables / Disables Telemetry
+ *
+ * @param telemetryEnabled True to start telemetry, false to stop it
+ */
+ public void setTelemetryEnabled(boolean telemetryEnabled) {
+ //Timber.i("this.telemetryEnabled = " + this.telemetryEnabled + "; telemetryEnabled = " + telemetryEnabled);
+ if (this.telemetryEnabled == telemetryEnabled) {
+ //Timber.d("No need to start / stop telemetry as it's already in that state.");
+ return;
}
- public boolean isTelemetryEnabled() {
- return telemetryEnabled;
- }
+ if (telemetryEnabled) {
+ //Timber.d("Starting Telemetry Up!");
+ // Start It Up
+ context.startService(new Intent(context, TelemetryService.class));
- /**
- * Enables / Disables Telemetry
- * @param telemetryEnabled True to start telemetry, false to stop it
- */
- public void setTelemetryEnabled(boolean telemetryEnabled) {
- Log.i(TAG, "setTelemetryEnabled(); this.telemetryEnabled = " + this.telemetryEnabled + "; telemetryEnabled = " + telemetryEnabled);
- if (this.telemetryEnabled == telemetryEnabled) {
- Log.d(TAG, "No need to start / stop telemetry as it's already in that state.");
- return;
+ // Make sure Ambient Mode is started at a minimum
+ if (LocationServices.getLocationServices(context).areLocationPermissionsGranted()) {
+ //Timber.i("Permissions are good, see if GPS is enabled and if not then setup Ambient.");
+ if (LocationServices.getLocationServices(context).isGpsEnabled()) {
+ LocationServices.getLocationServices(context).toggleGPS(false);
}
+ } else {
+ // Start timer that checks for Permissions
+ //Timber.i("Permissions are not good. Need to do some looping to check on stuff.");
- if (telemetryEnabled) {
- Log.d(TAG, "Starting Telemetry Up!");
- // Start It Up
- context.startService(new Intent(context, TelemetryService.class));
+ final Handler permsHandler = new Handler();
+ Runnable runnable = new Runnable() {
- // Make sure Ambient Mode is started at a minimum
+ private final ExponentialBackoffCounter exponentialBackoffCounter = new ExponentialBackoffCounter();
+
+ @Override
+ public void run() {
if (LocationServices.getLocationServices(context).areLocationPermissionsGranted()) {
- Log.i(TAG, "Permissions are good, see if GPS is enabled and if not then setup Ambient.");
- if (LocationServices.getLocationServices(context).isGPSEnabled()) {
- LocationServices.getLocationServices(context).toggleGPS(false);
- }
+ //Timber.i("Permissions finally granted, so starting Ambient if GPS isn't already enabled");
+ // Start Ambient
+ if (LocationServices.getLocationServices(context).isGpsEnabled()) {
+ LocationServices.getLocationServices(context).toggleGPS(false);
+ }
} else {
- // Start timer that checks for Permissions
- Log.i(TAG, "Permissions are not good. Need to do some looping to check on stuff.");
-
- final Handler permsHandler = new Handler();
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- if (LocationServices.getLocationServices(context).areLocationPermissionsGranted()) {
- Log.i(TAG, "Permissions finally granted, so starting Ambient if GPS isn't already enabled");
- // Start Ambient
- if (LocationServices.getLocationServices(context).isGPSEnabled()) {
- LocationServices.getLocationServices(context).toggleGPS(false);
- }
- } else {
- // Restart Handler
- Log.i(TAG, "Permissions not granted yet... let's try again in 30 seconds");
- permsHandler.postDelayed(this, 1000 * 30);
- }
- }
- };
- permsHandler.postDelayed(runnable, 1000 * 10);
- }
-
- // Manage Timer Flush
- timer = new Timer();
- timer.schedule(new FlushEventsTimerTask(), flushDelayInitialInMillis, flushDelayInMillis);
- } else {
- Log.d(TAG, "Shutting Telemetry Down");
- // Shut It Down
- events.removeAllElements();
- context.stopService(new Intent(context, TelemetryService.class));
-
- if (timer != null) {
- timer.cancel();
- timer = null;
+ // Restart Handler
+ long nextWaitTime = exponentialBackoffCounter.getNextCount();
+ //Timber.i("Permissions not granted yet... let's try again in " + nextWaitTime/1000 + " seconds");
+ permsHandler.postDelayed(this, nextWaitTime);
}
- }
-
- // Persist
- this.telemetryEnabled = telemetryEnabled;
- SharedPreferences prefs = context.getSharedPreferences(MapboxConstants.MAPBOX_SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putBoolean(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED, telemetryEnabled);
- editor.apply();
- editor.commit();
+ }
+ };
+ permsHandler.postDelayed(runnable, 1000 * 10);
+ }
+
+ // Manage Timer Flush
+ timer = new Timer();
+ timer.schedule(new FlushEventsTimerTask(), flushDelayInitialInMillis, flushDelayInMillis);
+ } else {
+ //Timber.d("Shutting Telemetry Down");
+ // Shut It Down
+ events.removeAllElements();
+ context.stopService(new Intent(context, TelemetryService.class));
+
+ if (timer != null) {
+ timer.cancel();
+ timer = null;
+ }
}
- /**
- * Immediately attempt to send all events data in the queue to the server.
- *
- * NOTE: Permission set to package private to enable only telemetry code to use this.
- */
- void flushEventsQueueImmediately() {
- Log.i(TAG, "flushEventsQueueImmediately() called...");
- new FlushTheEventsTask().execute();
+ // Persist
+ this.telemetryEnabled = telemetryEnabled;
+ SharedPreferences prefs = context.getSharedPreferences(MapboxConstants.MAPBOX_SHARED_PREFERENCES_FILE,
+ Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED, telemetryEnabled);
+ editor.apply();
+ editor.commit();
+ }
+
+ /**
+ * Immediately attempt to send all events data in the queue to the server.
+ * <p>
+ * NOTE: Permission set to package private to enable only telemetry code to use this.
+ */
+ void flushEventsQueueImmediately() {
+ //Timber.i("flushEventsQueueImmediately() called...");
+ new FlushTheEventsTask().execute();
+ }
+
+ /**
+ * Centralized method for adding populated event to the queue allowing for cap size checking
+ *
+ * @param event Event to add to the Events Queue
+ */
+ private void putEventOnQueue(@NonNull Hashtable<String, Object> event) {
+ if (event == null) {
+ return;
}
-
- /**
- * Centralized method for adding populated event to the queue allowing for cap size checking
- * @param event Event to add to the Events Queue
- */
- private void putEventOnQueue(@NonNull Hashtable<String, Object> event) {
- if (event == null) {
- return;
- }
- events.add(event);
- if (events.size() == FLUSH_EVENTS_CAP) {
- Log.d(TAG, "eventsSize == flushCap so send data.");
- flushEventsQueueImmediately();
- }
+ events.add(event);
+ if (events.size() == FLUSH_EVENTS_CAP) {
+ //Timber.d("eventsSize == flushCap so send data.");
+ flushEventsQueueImmediately();
}
-
- /**
- * Adds a Location Event to the system for processing
- * @param location Location event
- */
- public void addLocationEvent(Location location) {
-
- // NaN and Infinite checks to prevent JSON errors at send to server time
- if (Double.isNaN(location.getLatitude()) || Double.isNaN(location.getLongitude()) || Double.isNaN(location.getAltitude())) {
- return;
- }
-
- if (Double.isInfinite(location.getLatitude()) || Double.isInfinite(location.getLongitude()) || Double.isInfinite(location.getAltitude())) {
- return;
- }
-
- // Add Location even to queue
- Hashtable<String, Object> event = new Hashtable<>();
- event.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_LOCATION);
- event.put(MapboxEvent.ATTRIBUTE_CREATED, generateCreateDate());
- event.put(MapboxEvent.ATTRIBUTE_SOURCE, MapboxEvent.SOURCE_MAPBOX);
- event.put(MapboxEvent.ATTRIBUTE_SESSION_ID, encodeString(mapboxSessionId));
- event.put(MapboxEvent.KEY_LATITUDE, Math.floor(location.getLatitude() * locationEventAccuracy) / locationEventAccuracy);
- event.put(MapboxEvent.KEY_LONGITUDE, Math.floor(location.getLongitude() * locationEventAccuracy) / locationEventAccuracy);
- event.put(MapboxEvent.KEY_ALTITUDE, location.getAltitude());
- event.put(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, operatingSystem);
- event.put(MapboxEvent.ATTRIBUTE_APPLICATION_STATE, getApplicationState());
-
- putEventOnQueue(event);
-
- rotateSessionId();
+ }
+
+ /**
+ * Adds a Location Event to the system for processing
+ *
+ * @param location Location event
+ */
+ public void addLocationEvent(Location location) {
+
+ // NaN and Infinite checks to prevent JSON errors at send to server time
+ if (Double.isNaN(location.getLatitude()) || Double.isNaN(location.getLongitude())
+ || Double.isNaN(location.getAltitude()) || Float.isNaN(location.getAccuracy())) {
+ return;
}
- /**
- * Push Interactive Events to the system for processing
- *
- * @param eventWithAttributes Event with attributes
- */
- public void pushEvent(Hashtable<String, Object> eventWithAttributes) {
- if (context == null || accessToken == null) {
- return;
- }
-
- if (eventWithAttributes == null) {
- return;
- }
-
- String eventType = (String) eventWithAttributes.get(MapboxEvent.ATTRIBUTE_EVENT);
- if (TextUtils.isEmpty(eventType)) {
- return;
- }
-
- if (eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_LOAD)) {
- // Map Load Data Model
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_USERID, mapboxVendorId);
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_MODEL, Build.MODEL);
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, operatingSystem);
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_RESOLUTION, displayMetrics.density);
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE, getAccesibilityFontScaleSize());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ORIENTATION, getOrientation());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_PLUGGED_IN, isPluggedIn());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CARRIER, getCellularCarrier());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_WIFI, getConnectedToWifi());
-
- // Put Map Load on events before Turnstile clears it
- putEventOnQueue(eventWithAttributes);
-
- // Turnstile
- pushTurnstileEvent();
-
- // Return immediately to avoid double adding of event
- return;
-
- } else if (eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_CLICK)) {
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ORIENTATION, getOrientation());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_PLUGGED_IN, isPluggedIn());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CARRIER, getCellularCarrier());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_WIFI, getConnectedToWifi());
- } else if (eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_DRAGEND)) {
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ORIENTATION, getOrientation());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_PLUGGED_IN, isPluggedIn());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CARRIER, getCellularCarrier());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType());
- eventWithAttributes.put(MapboxEvent.ATTRIBUTE_WIFI, getConnectedToWifi());
- } else {
- Log.w(TAG, "This is not an event type in the Events Data Model.");
- return;
- }
-
- putEventOnQueue(eventWithAttributes);
+ if (Double.isInfinite(location.getLatitude()) || Double.isInfinite(location.getLongitude())
+ || Double.isInfinite(location.getAltitude()) || Float.isInfinite(location.getAccuracy())) {
+ return;
}
- /**
- * Pushes turnstile event for internal billing purposes
- */
- private void pushTurnstileEvent() {
-
- Hashtable<String, Object> event = new Hashtable<>();
- event.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_TURNSTILE);
- event.put(MapboxEvent.ATTRIBUTE_CREATED, generateCreateDate());
- event.put(MapboxEvent.ATTRIBUTE_USERID, mapboxVendorId);
- event.put(MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY, telemetryEnabled);
-
- events.add(event);
-
- // Send to Server Immediately
- flushEventsQueueImmediately();
- Log.d(TAG, "turnstile event pushed.");
+ // Add Location even to queue
+ Hashtable<String, Object> event = new Hashtable<>();
+ event.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_LOCATION);
+ event.put(MapboxEvent.ATTRIBUTE_CREATED, generateCreateDate());
+ event.put(MapboxEvent.ATTRIBUTE_SOURCE, MapboxEvent.SOURCE_MAPBOX);
+ event.put(MapboxEvent.ATTRIBUTE_SESSION_ID, encodeString(mapboxSessionId));
+ event.put(MapboxEvent.KEY_LATITUDE,
+ Math.floor(location.getLatitude() * locationEventAccuracy) / locationEventAccuracy);
+ event.put(MapboxEvent.KEY_LONGITUDE,
+ Math.floor(location.getLongitude() * locationEventAccuracy) / locationEventAccuracy);
+ event.put(MapboxEvent.KEY_ALTITUDE, location.getAltitude());
+ event.put(MapboxEvent.KEY_HORIZONTAL_ACCURACY, Math.round(location.getAccuracy()));
+ event.put(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, operatingSystem);
+ event.put(MapboxEvent.ATTRIBUTE_APPLICATION_STATE, getApplicationState());
+
+ putEventOnQueue(event);
+
+ rotateSessionId();
+ }
+
+ /**
+ * Push Interactive Events to the system for processing
+ *
+ * @param eventWithAttributes Event with attributes
+ */
+ public void pushEvent(Hashtable<String, Object> eventWithAttributes) {
+ if (context == null || accessToken == null) {
+ return;
}
- /**
- * SHA-1 Encoding for strings
- * @param string String to encode
- * @return String encoded if no error, original string if error
- */
- private String encodeString(String string) {
- try {
- if (messageDigest != null) {
- messageDigest.reset();
- messageDigest.update(string.getBytes("UTF-8"));
- byte[] bytes = messageDigest.digest();
-
- // Get the Hex version of the digest
- StringBuilder sb = new StringBuilder();
- for (byte b : bytes) {
- sb.append( String.format("%02X", b) );
- }
- String hex = sb.toString();
-
- return hex;
- }
- } catch (Exception e) {
- Log.w(TAG, "Error encoding string, will return in original form." + e);
- }
- return string;
+ if (eventWithAttributes == null) {
+ return;
}
- /**
- * Changes Session Id based on time boundary
- */
- private void rotateSessionId() {
- long now = System.currentTimeMillis();
- if ((TextUtils.isEmpty(mapboxSessionId)) || (now - mapboxSessionIdLastSet > (SESSION_ID_ROTATION_HOURS * hourInMillis))) {
- mapboxSessionId = UUID.randomUUID().toString();
- mapboxSessionIdLastSet = System.currentTimeMillis();
- }
+ String eventType = (String) eventWithAttributes.get(MapboxEvent.ATTRIBUTE_EVENT);
+ if (TextUtils.isEmpty(eventType)) {
+ return;
}
- private String getOrientation() {
- switch (context.getResources().getConfiguration().orientation) {
- case Configuration.ORIENTATION_LANDSCAPE:
- return "Landscape";
- case Configuration.ORIENTATION_PORTRAIT:
- return "Portrait";
- default:
- return "";
- }
+ if (eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_LOAD)) {
+ // Map Load Data Model
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_USERID, mapboxVendorId);
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_MODEL, Build.MODEL);
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, operatingSystem);
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_RESOLUTION, displayMetrics.density);
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE, getAccesibilityFontScaleSize());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ORIENTATION, getOrientation());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_PLUGGED_IN, isPluggedIn());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CARRIER, getCellularCarrier());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_WIFI, getConnectedToWifi());
+
+ // Put Map Load on events before Turnstile clears it
+ putEventOnQueue(eventWithAttributes);
+
+ // Turnstile
+ pushTurnstileEvent();
+
+ // Return immediately to avoid double adding of event
+ return;
+
+ } else if (eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_CLICK)) {
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ORIENTATION, getOrientation());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_PLUGGED_IN, isPluggedIn());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CARRIER, getCellularCarrier());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_WIFI, getConnectedToWifi());
+ } else if (eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_DRAGEND)) {
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ORIENTATION, getOrientation());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_PLUGGED_IN, isPluggedIn());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CARRIER, getCellularCarrier());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType());
+ eventWithAttributes.put(MapboxEvent.ATTRIBUTE_WIFI, getConnectedToWifi());
+ } else {
+ //Timber.w("This is not an event type in the Events Data Model.");
+ return;
}
- private int getBatteryLevel() {
- int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
- int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
+ putEventOnQueue(eventWithAttributes);
+ }
+
+ /**
+ * Pushes turnstile event for internal billing purposes
+ */
+ private void pushTurnstileEvent() {
+
+ Hashtable<String, Object> event = new Hashtable<>();
+ event.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_TURNSTILE);
+ event.put(MapboxEvent.ATTRIBUTE_CREATED, generateCreateDate());
+ event.put(MapboxEvent.ATTRIBUTE_USERID, mapboxVendorId);
+ event.put(MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY, telemetryEnabled);
+
+ events.add(event);
+
+ // Send to Server Immediately
+ flushEventsQueueImmediately();
+ //Timber.d("turnstile event pushed.");
+ }
+
+ /**
+ * SHA-1 Encoding for strings
+ *
+ * @param string String to encode
+ * @return String encoded if no error, original string if error
+ */
+ private String encodeString(String string) {
+ try {
+ if (messageDigest != null) {
+ messageDigest.reset();
+ messageDigest.update(string.getBytes("UTF-8"));
+ byte[] bytes = messageDigest.digest();
+
+ // Get the Hex version of the digest
+ StringBuilder sb = new StringBuilder();
+ for (byte b : bytes) {
+ sb.append(String.format("%02X", b));
+ }
+ String hex = sb.toString();
- return Math.round((level / (float)scale) * 100);
+ return hex;
+ }
+ } catch (Exception exception) {
+ //Timber.w("Error encoding string, will return in original form.", exception);
+ }
+ return string;
+ }
+
+ /**
+ * Changes Session Id based on time boundary
+ */
+ private void rotateSessionId() {
+ long now = System.currentTimeMillis();
+ if ((TextUtils.isEmpty(mapboxSessionId))
+ || (now - mapboxSessionIdLastSet > (SESSION_ID_ROTATION_HOURS * hourInMillis))) {
+ mapboxSessionId = UUID.randomUUID().toString();
+ mapboxSessionIdLastSet = System.currentTimeMillis();
+ }
+ }
+
+ private String getOrientation() {
+ switch (context.getResources().getConfiguration().orientation) {
+ case Configuration.ORIENTATION_LANDSCAPE:
+ return "Landscape";
+ case Configuration.ORIENTATION_PORTRAIT:
+ return "Portrait";
+ default:
+ return "";
+ }
+ }
+
+ private int getBatteryLevel() {
+ int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
+ int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
+
+ return Math.round((level / (float) scale) * 100);
+ }
+
+ /**
+ * Determine if device is plugged in to power via USB or AC or not.
+ * <p>
+ * http://developer.android.com/reference/android/os/BatteryManager.html#EXTRA_PLUGGED
+ *
+ * @return true if plugged in, false if not
+ */
+ private boolean isPluggedIn() {
+
+ int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
+ if (chargePlug == BatteryManager.BATTERY_PLUGGED_USB || chargePlug == BatteryManager.BATTERY_PLUGGED_AC) {
+ return true;
}
- /**
- * Determine if device is plugged in to power via USB or AC or not.
- *
- * http://developer.android.com/reference/android/os/BatteryManager.html#EXTRA_PLUGGED
- * @return true if plugged in, false if not
- */
- private boolean isPluggedIn() {
+ return false;
+ }
- int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
- if (chargePlug == BatteryManager.BATTERY_PLUGGED_USB || chargePlug == BatteryManager.BATTERY_PLUGGED_AC) {
- return true;
- }
+ private String getApplicationState() {
- return false;
+ ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
+ if (appProcesses == null) {
+ return "";
}
-
- private String getApplicationState() {
-
- ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
- if (appProcesses == null) {
- return "";
- }
- final String packageName = context.getPackageName();
- for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
- if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
- return "Foreground";
- }
- }
- return "Background";
+ final String packageName = context.getPackageName();
+ for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
+ if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
+ && appProcess.processName.equals(packageName)) {
+ return "Foreground";
+ }
}
-
- private float getAccesibilityFontScaleSize() {
- // Values
- // Small = 0.85
- // Normal = 1.0
- // Large = 1.15
- // Huge = 1.3
-
- return context.getResources().getConfiguration().fontScale;
+ return "Background";
+ }
+
+ private float getAccesibilityFontScaleSize() {
+ // Values
+ // Small = 0.85
+ // Normal = 1.0
+ // Large = 1.15
+ // Huge = 1.3
+
+ return context.getResources().getConfiguration().fontScale;
+ }
+
+ private String getCellularCarrier() {
+ TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ String carrierName = manager.getNetworkOperatorName();
+ if (TextUtils.isEmpty(carrierName)) {
+ carrierName = "";
}
-
- private String getCellularCarrier() {
- TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
- String carrierName = manager.getNetworkOperatorName();
- if (TextUtils.isEmpty(carrierName)) {
- carrierName = "";
- }
- return carrierName;
+ return carrierName;
+ }
+
+ private String getCellularNetworkType() {
+ TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ switch (manager.getNetworkType()) {
+ case TelephonyManager.NETWORK_TYPE_1xRTT:
+ return "1xRTT";
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ return "CDMA";
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ return "EDGE";
+ case TelephonyManager.NETWORK_TYPE_EHRPD:
+ return "EHRPD";
+ case TelephonyManager.NETWORK_TYPE_EVDO_0:
+ return "EVDO_0";
+ case TelephonyManager.NETWORK_TYPE_EVDO_A:
+ return "EVDO_A";
+ case TelephonyManager.NETWORK_TYPE_EVDO_B:
+ return "EVDO_B";
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ return "GPRS";
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ return "HSDPA";
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ return "HSPA";
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ return "HSPAP";
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ return "HSUPA";
+ case TelephonyManager.NETWORK_TYPE_IDEN:
+ return "IDEN";
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ return "LTE";
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ return "UMTS";
+ case TelephonyManager.NETWORK_TYPE_UNKNOWN:
+ return "Unknown";
+ default:
+ return "";
}
+ }
- private String getCellularNetworkType () {
- TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
- switch (manager.getNetworkType()) {
- case TelephonyManager.NETWORK_TYPE_1xRTT:
- return "1xRTT";
- case TelephonyManager.NETWORK_TYPE_CDMA:
- return "CDMA";
- case TelephonyManager.NETWORK_TYPE_EDGE:
- return "EDGE";
- case TelephonyManager.NETWORK_TYPE_EHRPD:
- return "EHRPD";
- case TelephonyManager.NETWORK_TYPE_EVDO_0:
- return "EVDO_0";
- case TelephonyManager.NETWORK_TYPE_EVDO_A:
- return "EVDO_A";
- case TelephonyManager.NETWORK_TYPE_EVDO_B:
- return "EVDO_B";
- case TelephonyManager.NETWORK_TYPE_GPRS:
- return "GPRS";
- case TelephonyManager.NETWORK_TYPE_HSDPA:
- return "HSDPA";
- case TelephonyManager.NETWORK_TYPE_HSPA:
- return "HSPA";
- case TelephonyManager.NETWORK_TYPE_HSPAP:
- return "HSPAP";
- case TelephonyManager.NETWORK_TYPE_HSUPA:
- return "HSUPA";
- case TelephonyManager.NETWORK_TYPE_IDEN:
- return "IDEN";
- case TelephonyManager.NETWORK_TYPE_LTE:
- return "LTE";
- case TelephonyManager.NETWORK_TYPE_UMTS:
- return "UMTS";
- case TelephonyManager.NETWORK_TYPE_UNKNOWN:
- return "Unknown";
- default:
- return "";
- }
- }
+ public Boolean getConnectedToWifi() {
- public Boolean getConnectedToWifi() {
-
- Boolean status = false;
- WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
- if (wifiMgr.isWifiEnabled()) {
- try {
- WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
- if (wifiInfo.getNetworkId() != -1){
- status = true;
- }
- } catch (Exception e) {
- Log.w(TAG, "Error getting Wifi Connection Status: " + e);
- status = false;
- }
+ Boolean status = false;
+ WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ if (wifiMgr.isWifiEnabled()) {
+ try {
+ WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
+ if (wifiInfo.getNetworkId() != -1) {
+ status = true;
}
-
- return status;
+ } catch (Exception exception) {
+ //Timber.w("Error getting Wifi Connection Status: ", exception);
+ status = false;
+ }
}
-
- /**
- * Task responsible for converting stored events and sending them to the server
- */
- private class FlushTheEventsTask extends AsyncTask<Void, Void, Void> {
-
- @Override
- protected Void doInBackground(Void... voids) {
-
- if (events.isEmpty()) {
- Log.d(TAG, "No events in the queue to send so returning.");
- return null;
+ return status;
+ }
+
+
+ /**
+ * Task responsible for converting stored events and sending them to the server
+ */
+ private class FlushTheEventsTask extends AsyncTask<Void, Void, Void> {
+
+ @Override
+ protected Void doInBackground(Void... voids) {
+
+ if (events.isEmpty()) {
+ //Timber.d("No events in the queue to send so returning.");
+ return null;
+ }
+
+ // Check for NetworkConnectivity
+ if (!Mapbox.isConnected()) {
+ //Timber.w("Not connected to network, so empty events cache and return without attempting to send events");
+ // Make sure that events don't pile up when Offline
+ // and thus impact available memory over time.
+ events.removeAllElements();
+ return null;
+ }
+
+ Response response = null;
+
+ try {
+ // Send data
+ // =========
+ JSONArray jsonArray = new JSONArray();
+
+ Vector<Hashtable<String, Object>> eventsClone = (Vector<Hashtable<String, Object>>) events.clone();
+
+ for (Hashtable<String, Object> evt : eventsClone) {
+ JSONObject jsonObject = new JSONObject();
+
+ // Build the JSON but only if there's a value for it in the evt
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_EVENT, evt.get(MapboxEvent.ATTRIBUTE_EVENT));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_CREATED, evt.get(MapboxEvent.ATTRIBUTE_CREATED));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_USERID, evt.get(MapboxEvent.ATTRIBUTE_USERID));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY, evt.get(MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_SOURCE, evt.get(MapboxEvent.ATTRIBUTE_SOURCE));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_SESSION_ID, evt.get(MapboxEvent.ATTRIBUTE_SESSION_ID));
+ jsonObject.putOpt(MapboxEvent.KEY_LATITUDE, evt.get(MapboxEvent.KEY_LATITUDE));
+
+ // Make sure Longitude Is Wrapped
+ if (evt.containsKey(MapboxEvent.KEY_LONGITUDE)) {
+ double lon = (double) evt.get(MapboxEvent.KEY_LONGITUDE);
+ if ((lon < GeoConstants.MIN_LONGITUDE) || (lon > GeoConstants.MAX_LONGITUDE)) {
+ lon = MathUtils.wrap(lon, GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE);
}
-
- // Check for NetworkConnectivity
- if (!MapboxAccountManager.getInstance().isConnected()) {
- Log.w(TAG, "Not connected to network, so empty events cache and return without attempting to send events");
- // Make sure that events don't pile up when Offline
- // and thus impact available memory over time.
- events.removeAllElements();
- return null;
+ jsonObject.put(MapboxEvent.KEY_LONGITUDE, lon);
+ }
+
+ jsonObject.putOpt(MapboxEvent.KEY_ALTITUDE, evt.get(MapboxEvent.KEY_ALTITUDE));
+ jsonObject.putOpt(MapboxEvent.KEY_ZOOM, evt.get(MapboxEvent.KEY_ZOOM));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, evt.get(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_USERID, evt.get(MapboxEvent.ATTRIBUTE_USERID));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_MODEL, evt.get(MapboxEvent.ATTRIBUTE_MODEL));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_RESOLUTION, evt.get(MapboxEvent.ATTRIBUTE_RESOLUTION));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE,
+ evt.get(MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, evt.get(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_PLUGGED_IN, evt.get(MapboxEvent.ATTRIBUTE_PLUGGED_IN));
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_WIFI, evt.get(MapboxEvent.ATTRIBUTE_WIFI));
+
+ // Special Cases where empty string is denoting null and therefore should not be sent at all
+ // This arises as thread safe Hashtable does not accept null values (nor keys)
+ if (evt.containsKey(MapboxEvent.ATTRIBUTE_ORIENTATION)) {
+ String orientation = (String) evt.get(MapboxEvent.ATTRIBUTE_ORIENTATION);
+ if (!TextUtils.isEmpty(orientation)) {
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_ORIENTATION, orientation);
}
-
- Response response = null;
-
- try {
- // Send data
- // =========
- JSONArray jsonArray = new JSONArray();
-
- Vector<Hashtable<String, Object>> eventsClone = (Vector<Hashtable<String, Object>>) events.clone();
-
- for (Hashtable<String, Object> evt : eventsClone) {
- JSONObject jsonObject = new JSONObject();
-
- // Build the JSON but only if there's a value for it in the evt
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_EVENT, evt.get(MapboxEvent.ATTRIBUTE_EVENT));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_CREATED, evt.get(MapboxEvent.ATTRIBUTE_CREATED));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_USERID, evt.get(MapboxEvent.ATTRIBUTE_USERID));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY, evt.get(MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_SOURCE, evt.get(MapboxEvent.ATTRIBUTE_SOURCE));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_SESSION_ID, evt.get(MapboxEvent.ATTRIBUTE_SESSION_ID));
- jsonObject.putOpt(MapboxEvent.KEY_LATITUDE, evt.get(MapboxEvent.KEY_LATITUDE));
-
- // Make sure Longitude Is Wrapped
- if (evt.containsKey(MapboxEvent.KEY_LONGITUDE)) {
- double lon = (double)evt.get(MapboxEvent.KEY_LONGITUDE);
- if ((lon < GeoConstants.MIN_LONGITUDE) || (lon > GeoConstants.MAX_LONGITUDE)) {
- lon = MathUtils.wrap(lon, GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE);
- }
- jsonObject.put(MapboxEvent.KEY_LONGITUDE, lon);
- }
-
- jsonObject.putOpt(MapboxEvent.KEY_ALTITUDE, evt.get(MapboxEvent.KEY_ALTITUDE));
- jsonObject.putOpt(MapboxEvent.KEY_ZOOM, evt.get(MapboxEvent.KEY_ZOOM));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, evt.get(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_USERID, evt.get(MapboxEvent.ATTRIBUTE_USERID));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_MODEL, evt.get(MapboxEvent.ATTRIBUTE_MODEL));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_RESOLUTION, evt.get(MapboxEvent.ATTRIBUTE_RESOLUTION));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE, evt.get(MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, evt.get(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_PLUGGED_IN, evt.get(MapboxEvent.ATTRIBUTE_PLUGGED_IN));
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_WIFI, evt.get(MapboxEvent.ATTRIBUTE_WIFI));
-
- // Special Cases where empty string is denoting null and therefore should not be sent at all
- // This arises as thread safe Hashtable does not accept null values (nor keys)
- if (evt.containsKey(MapboxEvent.ATTRIBUTE_ORIENTATION)) {
- String orientation = (String)evt.get(MapboxEvent.ATTRIBUTE_ORIENTATION);
- if (!TextUtils.isEmpty(orientation)) {
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_ORIENTATION, orientation);
- }
- }
- if (evt.containsKey(MapboxEvent.ATTRIBUTE_CARRIER)) {
- String carrier = (String)evt.get(MapboxEvent.ATTRIBUTE_CARRIER);
- if (!TextUtils.isEmpty(carrier)) {
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_CARRIER, carrier);
- }
- }
- if (evt.containsKey(MapboxEvent.ATTRIBUTE_APPLICATION_STATE)) {
- String appState = (String)evt.get(MapboxEvent.ATTRIBUTE_APPLICATION_STATE);
- if (!TextUtils.isEmpty(appState)) {
- jsonObject.putOpt(MapboxEvent.ATTRIBUTE_APPLICATION_STATE, evt.get(MapboxEvent.ATTRIBUTE_APPLICATION_STATE));
- }
- }
-
- // Special Cases where null has to be passed if no value exists
- // Requires using put() instead of putOpt()
- String eventType = (String)evt.get(MapboxEvent.ATTRIBUTE_EVENT);
- if (!TextUtils.isEmpty(eventType) && eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_CLICK)) {
- jsonObject.put(MapboxEvent.KEY_GESTURE_ID, evt.get(MapboxEvent.KEY_GESTURE_ID));
- }
- if (evt.containsKey(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE)) {
- String cellularNetworkType = (String)evt.get(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE);
- if (TextUtils.isEmpty(cellularNetworkType)) {
- jsonObject.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, null);
- } else {
- jsonObject.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, evt.get(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE));
- }
- }
-
- jsonArray.put(jsonObject);
- }
-
- // Based on http://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html
- CertificatePinner.Builder certificatePinnerBuilder = new CertificatePinner.Builder();
- if(stagingEnv){
- // Staging - Geotrust
- certificatePinnerBuilder
- .add("cloudfront-staging.tilestream.net", "sha256/3euxrJOrEZI15R4104UsiAkDqe007EPyZ6eTL/XxdAY=")
- .add("cloudfront-staging.tilestream.net", "sha256/5kJvNEMw0KjrCAu7eXY5HZdvyCS13BbA0VJG1RSP91w=")
- .add("cloudfront-staging.tilestream.net", "sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=");
- }else{
- certificatePinnerBuilder
- // Prod - Geotrust
- .add("events.mapbox.com", "sha256/BhynraKizavqoC5U26qgYuxLZst6pCu9J5stfL6RSYY=")
- .add("events.mapbox.com", "sha256/owrR9U9FWDWtrFF+myoRIu75JwU4sJwzvhCNLZoY37g=")
- .add("events.mapbox.com", "sha256/SQVGZiOrQXi+kqxcvWWE96HhfydlLVqFr4lQTqI5qqo=")
- // Prod - DigiCert
- .add("events.mapbox.com", "sha256/Tb0uHZ/KQjWh8N9+CZFLc4zx36LONQ55l6laDi1qtT4=")
- .add("events.mapbox.com", "sha256/RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=")
- .add("events.mapbox.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=");
- }
-
- OkHttpClient client = new OkHttpClient.Builder()
- .certificatePinner(certificatePinnerBuilder.build())
- .addInterceptor(new GzipRequestInterceptor())
- .build();
- RequestBody body = RequestBody.create(JSON, jsonArray.toString());
-
- String url = eventsURL + "/events/v2?access_token=" + accessToken;
-
- Request request = new Request.Builder()
- .url(url)
- .header("User-Agent", userAgent)
- .post(body)
- .build();
- response = client.newCall(request).execute();
- Log.d(TAG, "response code = " + response.code() + " for events " + events.size());
-
- } catch (Exception e) {
- Log.e(TAG, "FlushTheEventsTask borked: " + e);
- e.printStackTrace();
- } finally {
- if (response != null && response.body() != null) {
- response.body().close();
- }
- // Reset Events
- // ============
- events.removeAllElements();
+ }
+ if (evt.containsKey(MapboxEvent.ATTRIBUTE_CARRIER)) {
+ String carrier = (String) evt.get(MapboxEvent.ATTRIBUTE_CARRIER);
+ if (!TextUtils.isEmpty(carrier)) {
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_CARRIER, carrier);
+ }
+ }
+ if (evt.containsKey(MapboxEvent.ATTRIBUTE_APPLICATION_STATE)) {
+ String appState = (String) evt.get(MapboxEvent.ATTRIBUTE_APPLICATION_STATE);
+ if (!TextUtils.isEmpty(appState)) {
+ jsonObject.putOpt(MapboxEvent.ATTRIBUTE_APPLICATION_STATE,
+ evt.get(MapboxEvent.ATTRIBUTE_APPLICATION_STATE));
+ }
+ }
+
+ // Special Cases where null has to be passed if no value exists
+ // Requires using put() instead of putOpt()
+ String eventType = (String) evt.get(MapboxEvent.ATTRIBUTE_EVENT);
+ if (!TextUtils.isEmpty(eventType) && eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_CLICK)) {
+ jsonObject.put(MapboxEvent.KEY_GESTURE_ID, evt.get(MapboxEvent.KEY_GESTURE_ID));
+ }
+ if (evt.containsKey(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE)) {
+ String cellularNetworkType = (String) evt.get(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE);
+ if (TextUtils.isEmpty(cellularNetworkType)) {
+ jsonObject.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, null);
+ } else {
+ jsonObject.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE,
+ evt.get(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE));
}
+ }
+
+ jsonArray.put(jsonObject);
+ }
+
+ // Based on http://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html
+ CertificatePinner.Builder certificatePinnerBuilder = new CertificatePinner.Builder();
+ if (stagingEnv) {
+ // Staging - Geotrust
+ certificatePinnerBuilder
+ .add("cloudfront-staging.tilestream.net", "sha256/3euxrJOrEZI15R4104UsiAkDqe007EPyZ6eTL/XxdAY=")
+ .add("cloudfront-staging.tilestream.net", "sha256/5kJvNEMw0KjrCAu7eXY5HZdvyCS13BbA0VJG1RSP91w=")
+ .add("cloudfront-staging.tilestream.net", "sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=");
+ } else {
+ certificatePinnerBuilder
+ // Prod - Geotrust
+ .add("events.mapbox.com", "sha256/BhynraKizavqoC5U26qgYuxLZst6pCu9J5stfL6RSYY=")
+ .add("events.mapbox.com", "sha256/owrR9U9FWDWtrFF+myoRIu75JwU4sJwzvhCNLZoY37g=")
+ .add("events.mapbox.com", "sha256/SQVGZiOrQXi+kqxcvWWE96HhfydlLVqFr4lQTqI5qqo=")
+ // Prod - DigiCert
+ .add("events.mapbox.com", "sha256/Tb0uHZ/KQjWh8N9+CZFLc4zx36LONQ55l6laDi1qtT4=")
+ .add("events.mapbox.com", "sha256/RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=")
+ .add("events.mapbox.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=");
+ }
- return null;
+ OkHttpClient client = new OkHttpClient.Builder()
+ .certificatePinner(certificatePinnerBuilder.build())
+ .addInterceptor(new GzipRequestInterceptor())
+ .build();
+ RequestBody body = RequestBody.create(JSON, jsonArray.toString());
+
+ String url = eventsURL + "/events/v2?access_token=" + accessToken;
+
+ Request request = new Request.Builder()
+ .url(url)
+ .header("User-Agent", userAgent)
+ .post(body)
+ .build();
+ response = client.newCall(request).execute();
+ //Timber.d("response code = " + response.code() + " for events " + events.size());
+
+ } catch (Exception exception) {
+ Timber.e("FlushTheEventsTask borked: ", exception);
+ } finally {
+ if (response != null && response.body() != null) {
+ response.body().close();
}
+ // Reset Events
+ // ============
+ events.removeAllElements();
+ }
+ return null;
}
+ }
+
+ /**
+ * TimerTask responsible for sending event data to server
+ */
+ private class FlushEventsTimerTask extends TimerTask {
/**
- * TimerTask responsible for sending event data to server
+ * The task to run should be specified in the implementation of the {@code run()}
+ * method.
*/
- private class FlushEventsTimerTask extends TimerTask {
- /**
- * The task to run should be specified in the implementation of the {@code run()}
- * method.
- */
- @Override
- public void run() {
- new FlushTheEventsTask().execute();
- }
+ @Override
+ public void run() {
+ new FlushTheEventsTask().execute();
}
+ }
+
+ private String getApplicationIdentifier() {
+ try {
+ PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
+ return String.format(MapboxConstants.MAPBOX_LOCALE, "%s/%s/%s", context.getPackageName(),
+ packageInfo.versionName, packageInfo.versionCode);
+ } catch (Exception exception) {
+ return "";
+ }
+ }
- private String getApplicationIdentifier() {
- try {
- PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
- return String.format(MapboxConstants.MAPBOX_LOCALE, "%s/%s/%s", context.getPackageName(), packageInfo.versionName, packageInfo.versionCode);
- } catch (Exception e) {
- return "";
- }
+ static class ExponentialBackoffCounter {
+
+ private static final long BASE_TIME = 30000 /*30 seconds*/;
+ private int attempt;
+
+ long getNextCount() {
+ attempt++;
+ return attempt * BASE_TIME;
}
-}
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java
index c18da41e4b..2274fb2b82 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java
@@ -5,68 +5,66 @@ import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
-import android.os.Handler;
-import android.util.Log;
/**
* Listener for Location updates generated by implementing app.
*/
public class TelemetryLocationReceiver extends BroadcastReceiver {
- private static final String TAG = "TelemLocationReceiver";
+ public static final String INTENT_STRING = "com.mapbox.mapboxsdk.telemetry.TelemetryLocationReceiver";
- public static final String INTENT_STRING = "com.mapbox.mapboxsdk.telemetry.TelemetryLocationReceiver";
+ /**
+ * Default Constructor
+ */
+ public TelemetryLocationReceiver() {
+ super();
+ }
- /**
- * Default Constructor
- */
- public TelemetryLocationReceiver() {
- super();
+ /**
+ * This method is called when the BroadcastReceiver is receiving an Intent
+ * broadcast. During this time you can use the other methods on
+ * BroadcastReceiver to view/modify the current result values. This method
+ * is always called within the main thread of its process, unless you
+ * explicitly asked for it to be scheduled on a different thread using
+ * {@link Context#registerReceiver(BroadcastReceiver,
+ * android.content.IntentFilter, String, android.os.Handler)}. When it runs on the main
+ * thread you should
+ * never perform long-running operations in it (there is a timeout of
+ * 10 seconds that the system allows before considering the receiver to
+ * be blocked and a candidate to be killed). You cannot launch a popup dialog
+ * in your implementation of onReceive().
+ * <p>
+ * <p><b>If this BroadcastReceiver was launched through a &lt;receiver&gt; tag,
+ * then the object is no longer alive after returning from this
+ * function.</b> This means you should not perform any operations that
+ * return a result to you asynchronously -- in particular, for interacting
+ * with services, you should use
+ * {@link Context#startService(Intent)} instead of
+ * {@link Context#bindService(Intent, android.content.ServiceConnection, int)}. If you wish
+ * to interact with a service that is already running, you can use
+ * {@link #peekService}.
+ * <p>
+ * <p>The Intent filters used in {@link Context#registerReceiver}
+ * and in application manifests are <em>not</em> guaranteed to be exclusive. They
+ * are hints to the operating system about how to find suitable recipients. It is
+ * possible for senders to force delivery to specific recipients, bypassing filter
+ * resolution. For this reason, {@link #onReceive(Context, Intent) onReceive()}
+ * implementations should respond only to known actions, ignoring any unexpected
+ * Intents that they may receive.
+ *
+ * @param context The Context in which the receiver is running.
+ * @param intent The Intent being received.
+ */
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent == null || intent.getExtras() == null) {
+ // see https://github.com/mapbox/mapbox-gl-native/issues/6934
+ return;
}
- /**
- * This method is called when the BroadcastReceiver is receiving an Intent
- * broadcast. During this time you can use the other methods on
- * BroadcastReceiver to view/modify the current result values. This method
- * is always called within the main thread of its process, unless you
- * explicitly asked for it to be scheduled on a different thread using
- * {@link Context#registerReceiver(BroadcastReceiver,
- * IntentFilter, String, Handler)}. When it runs on the main
- * thread you should
- * never perform long-running operations in it (there is a timeout of
- * 10 seconds that the system allows before considering the receiver to
- * be blocked and a candidate to be killed). You cannot launch a popup dialog
- * in your implementation of onReceive().
- *
- * <p><b>If this BroadcastReceiver was launched through a &lt;receiver&gt; tag,
- * then the object is no longer alive after returning from this
- * function.</b> This means you should not perform any operations that
- * return a result to you asynchronously -- in particular, for interacting
- * with services, you should use
- * {@link Context#startService(Intent)} instead of
- * {@link Context#bindService(Intent, ServiceConnection, int)}. If you wish
- * to interact with a service that is already running, you can use
- * {@link #peekService}.
- *
- * <p>The Intent filters used in {@link Context#registerReceiver}
- * and in application manifests are <em>not</em> guaranteed to be exclusive. They
- * are hints to the operating system about how to find suitable recipients. It is
- * possible for senders to force delivery to specific recipients, bypassing filter
- * resolution. For this reason, {@link #onReceive(Context, Intent) onReceive()}
- * implementations should respond only to known actions, ignoring any unexpected
- * Intents that they may receive.
- *
- * @param context The Context in which the receiver is running.
- * @param intent The Intent being received.
- */
- @Override
- public void onReceive(Context context, Intent intent) {
- Location location = (Location)intent.getExtras().get(LocationManager.KEY_LOCATION_CHANGED);
- if (location != null) {
-// Log.d(TAG, "location received = " + location);
- MapboxEventManager.getMapboxEventManager().addLocationEvent(location);
- } else {
- Log.d(TAG, "location NOT received");
- }
+ Location location = (Location) intent.getExtras().get(LocationManager.KEY_LOCATION_CHANGED);
+ if (location != null) {
+ MapboxEventManager.getMapboxEventManager().addLocationEvent(location);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java
index 008f355f29..c667c1199d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java
@@ -8,148 +8,149 @@ import android.content.pm.ServiceInfo;
import android.os.AsyncTask;
import android.os.IBinder;
import android.support.annotation.Nullable;
-import android.util.Log;
+import android.support.v4.content.LocalBroadcastManager;
+
+import timber.log.Timber;
/**
* Manages Startup and Shutdown of Telemetry resources
*/
public class TelemetryService extends Service {
- private static final String TAG = "TelemetryService";
-
- private TelemetryLocationReceiver telemetryLocationReceiver = null;
-
- /**
- * Return the communication channel to the service. May return null if
- * clients can not bind to the service. The returned
- * {@link IBinder} is usually for a complex interface
- * that has been <a href="{@docRoot}guide/components/aidl.html">described using
- * aidl</a>.
- *
- * <p><em>Note that unlike other application components, calls on to the
- * IBinder interface returned here may not happen on the main thread
- * of the process</em>. More information about the main thread can be found in
- * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and
- * Threads</a>.</p>
- *
- * @param intent The Intent that was used to bind to this service,
- * as given to {@link Context#bindService
- * Context.bindService}. Note that any extras that were included with
- * the Intent at that point will <em>not</em> be seen here.
- * @return Return an IBinder through which clients can call on to the
- * service.
- */
- @Nullable
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
-
- /**
- * Called by the system when the service is first created. Do not call this method directly.
- */
- @Override
- public void onCreate() {
- super.onCreate();
-
- Log.i(TAG, "onCreate() called");
-
- // Enable Location Listening for lifecycle of app
- IntentFilter filter = new IntentFilter(TelemetryLocationReceiver.INTENT_STRING);
- telemetryLocationReceiver = new TelemetryLocationReceiver();
- registerReceiver(telemetryLocationReceiver, filter);
- }
-
- /**
- * Called by the system to notify a Service that it is no longer used and is being removed. The
- * service should clean up any resources it holds (threads, registered
- * receivers, etc) at this point. Upon return, there will be no more calls
- * in to this Service object and it is effectively dead. Do not call this method directly.
- */
- @Override
- public void onDestroy() {
- shutdownTelemetry();
- super.onDestroy();
+ private TelemetryLocationReceiver telemetryLocationReceiver = null;
+
+ /**
+ * Return the communication channel to the service. May return null if
+ * clients can not bind to the service. The returned
+ * {@link IBinder} is usually for a complex interface
+ * that has been <a href="{@docRoot}guide/components/aidl.html">described using
+ * aidl</a>.
+ * <p>
+ * <p><em>Note that unlike other application components, calls on to the
+ * IBinder interface returned here may not happen on the main thread
+ * of the process</em>. More information about the main thread can be found in
+ * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and
+ * Threads</a>.</p>
+ *
+ * @param intent The Intent that was used to bind to this service,
+ * as given to {@link Context#bindService
+ * Context.bindService}. Note that any extras that were included with
+ * the Intent at that point will <em>not</em> be seen here.
+ * @return Return an IBinder through which clients can call on to the
+ * service.
+ */
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+
+ /**
+ * Called by the system when the service is first created. Do not call this method directly.
+ */
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ Timber.i("onCreate() called");
+
+ // Enable Location Listening for lifecycle of app
+ LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(
+ new TelemetryLocationReceiver(),
+ new IntentFilter(TelemetryLocationReceiver.INTENT_STRING)
+ );
+ }
+
+ /**
+ * Called by the system to notify a Service that it is no longer used and is being removed. The
+ * service should clean up any resources it holds (threads, registered
+ * receivers, etc) at this point. Upon return, there will be no more calls
+ * in to this Service object and it is effectively dead. Do not call this method directly.
+ */
+ @Override
+ public void onDestroy() {
+ shutdownTelemetry();
+ super.onDestroy();
+ }
+
+ /**
+ * This is called if the service is currently running and the user has
+ * removed a task that comes from the service's application. If you have
+ * set {@link ServiceInfo#FLAG_STOP_WITH_TASK ServiceInfo.FLAG_STOP_WITH_TASK}
+ * then you will not receive this callback; instead, the service will simply
+ * be stopped.
+ *
+ * @param rootIntent The original root Intent that was used to launch
+ * the task that is being removed.
+ */
+ @Override
+ public void onTaskRemoved(Intent rootIntent) {
+ shutdownTelemetry();
+ super.onTaskRemoved(rootIntent);
+ }
+
+ /**
+ * Called by the system every time a client explicitly starts the service by calling
+ * {@link Context#startService}, providing the arguments it supplied and a
+ * unique integer token representing the start request. Do not call this method directly.
+ * <p>
+ * <p>For backwards compatibility, the default implementation calls
+ * {@link #onStart} and returns either {@link #START_STICKY}
+ * or {@link #START_STICKY_COMPATIBILITY}.
+ * </p>
+ * <p>If you need your application to run on platform versions prior to API
+ * level 5, you can use the following model to handle the older {@link #onStart}
+ * callback in that case. The <code>handleCommand</code> method is implemented by
+ * you as appropriate:
+ * </p>
+ * <p>
+ * <p class="caution">Note that the system calls this on your
+ * service's main thread. A service's main thread is the same
+ * thread where UI operations take place for Activities running in the
+ * same process. You should always avoid stalling the main
+ * thread's event loop. When doing long-running operations,
+ * network calls, or heavy disk I/O, you should kick off a new
+ * thread, or use {@link AsyncTask}.</p>
+ *
+ * @param intent The Intent supplied to {@link Context#startService},
+ * as given. This may be null if the service is being restarted after
+ * its process has gone away, and it had previously returned anything
+ * except {@link #START_STICKY_COMPATIBILITY}.
+ * @param flags Additional data about this start request. Currently either
+ * 0, {@link #START_FLAG_REDELIVERY}, or {@link #START_FLAG_RETRY}.
+ * @param startId A unique integer representing this specific request to
+ * start. Use with {@link #stopSelfResult(int)}.
+ * @return The return value indicates what semantics the system should
+ * use for the service's current started state. It may be one of the
+ * constants associated with the {@link #START_CONTINUATION_MASK} bits.
+ * @see #stopSelfResult(int)
+ */
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+
+ Timber.i("onStartCommand() called");
+
+ return START_NOT_STICKY;
+ }
+
+ private void shutdownTelemetry() {
+
+ // Send Any Remaining events to the server
+ MapboxEventManager.getMapboxEventManager().flushEventsQueueImmediately();
+
+ // Undesired, but needed trick to keep app alive long enough for data to get to server
+ try {
+ Thread.sleep(1000);
+ } catch (Exception exception) {
+ Timber.e("Error while trying to sleep for 1 second: " + exception);
}
- /**
- * This is called if the service is currently running and the user has
- * removed a task that comes from the service's application. If you have
- * set {@link ServiceInfo#FLAG_STOP_WITH_TASK ServiceInfo.FLAG_STOP_WITH_TASK}
- * then you will not receive this callback; instead, the service will simply
- * be stopped.
- *
- * @param rootIntent The original root Intent that was used to launch
- * the task that is being removed.
- */
- @Override
- public void onTaskRemoved(Intent rootIntent) {
- shutdownTelemetry();
- super.onTaskRemoved(rootIntent);
+ try {
+ unregisterReceiver(telemetryLocationReceiver);
+ } catch (IllegalArgumentException illegalArgumentException) {
+ Timber.e("Error when unregisterReceiver: " + illegalArgumentException);
}
- /**
- * Called by the system every time a client explicitly starts the service by calling
- * {@link Context#startService}, providing the arguments it supplied and a
- * unique integer token representing the start request. Do not call this method directly.
- *
- * <p>For backwards compatibility, the default implementation calls
- * {@link #onStart} and returns either {@link #START_STICKY}
- * or {@link #START_STICKY_COMPATIBILITY}.
- * </p>
- * <p>If you need your application to run on platform versions prior to API
- * level 5, you can use the following model to handle the older {@link #onStart}
- * callback in that case. The <code>handleCommand</code> method is implemented by
- * you as appropriate:
- * </p>
- *
- * <p class="caution">Note that the system calls this on your
- * service's main thread. A service's main thread is the same
- * thread where UI operations take place for Activities running in the
- * same process. You should always avoid stalling the main
- * thread's event loop. When doing long-running operations,
- * network calls, or heavy disk I/O, you should kick off a new
- * thread, or use {@link AsyncTask}.</p>
- *
- * @param intent The Intent supplied to {@link Context#startService},
- * as given. This may be null if the service is being restarted after
- * its process has gone away, and it had previously returned anything
- * except {@link #START_STICKY_COMPATIBILITY}.
- * @param flags Additional data about this start request. Currently either
- * 0, {@link #START_FLAG_REDELIVERY}, or {@link #START_FLAG_RETRY}.
- * @param startId A unique integer representing this specific request to
- * start. Use with {@link #stopSelfResult(int)}.
- * @return The return value indicates what semantics the system should
- * use for the service's current started state. It may be one of the
- * constants associated with the {@link #START_CONTINUATION_MASK} bits.
- * @see #stopSelfResult(int)
- */
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
-
- Log.i(TAG, "onStartCommand() called");
-
- return START_NOT_STICKY;
- }
-
- private void shutdownTelemetry() {
-
- // Send Any Remaining events to the server
- MapboxEventManager.getMapboxEventManager().flushEventsQueueImmediately();
-
- // Undesired, but needed trick to keep app alive long enough for data to get to server
- try {
- Thread.sleep(1000);
- } catch (Exception e) {
- Log.e(TAG, "Error while trying to sleep for 1 second: " + e);
- }
-
- try {
- unregisterReceiver(telemetryLocationReceiver);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Error when unregisterReceiver: " + e);
- }
-
- }
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java
index ab3b841043..7694604d9f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java
@@ -12,94 +12,98 @@ import android.view.View;
public class AnimatorUtils {
- public static void animate(@NonNull final View view, @AnimatorRes int animatorRes, @Nullable OnAnimationEndListener listener) {
- animate(view, animatorRes, -1, listener);
+ public static void animate(@NonNull final View view, @AnimatorRes int animatorRes,
+ @Nullable OnAnimationEndListener listener) {
+ animate(view, animatorRes, -1, listener);
+ }
+
+ public static void animate(final View view, @AnimatorRes int animatorRes, int duration,
+ @Nullable final OnAnimationEndListener listener) {
+ if (view == null) {
+ return;
}
- public static void animate(final View view, @AnimatorRes int animatorRes, int duration, @Nullable final OnAnimationEndListener listener) {
- if (view == null) {
- return;
- }
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ Animator animator = AnimatorInflater.loadAnimator(view.getContext(), animatorRes);
+ if (duration != -1) {
+ animator.setDuration(duration);
+ }
- view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- Animator animator = AnimatorInflater.loadAnimator(view.getContext(), animatorRes);
- if (duration != -1) {
- animator.setDuration(duration);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ view.setLayerType(View.LAYER_TYPE_NONE, null);
+ if (listener != null) {
+ listener.onAnimationEnd();
}
+ }
+ });
+ animator.setTarget(view);
+ animator.start();
+ }
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- view.setLayerType(View.LAYER_TYPE_NONE, null);
- if (listener != null) {
- listener.onAnimationEnd();
- }
- }
- });
- animator.setTarget(view);
- animator.start();
- }
+ public static void animate(@NonNull final View view, @AnimatorRes int animatorRes) {
+ animate(view, animatorRes, -1);
+ }
- public static void animate(@NonNull final View view, @AnimatorRes int animatorRes) {
- animate(view, animatorRes, -1);
- }
-
- public static void animate(@NonNull final View view, @AnimatorRes int animatorRes, int duration) {
- animate(view, animatorRes, duration, null);
- }
+ public static void animate(@NonNull final View view, @AnimatorRes int animatorRes, int duration) {
+ animate(view, animatorRes, duration, null);
+ }
- public static void rotate(@NonNull final View view, float rotation) {
- view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(view, View.ROTATION, view.getRotation(), rotation);
- rotateAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- view.setLayerType(View.LAYER_TYPE_NONE, null);
- }
- });
- rotateAnimator.start();
- }
+ public static void rotate(@NonNull final View view, float rotation) {
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(view, View.ROTATION, view.getRotation(), rotation);
+ rotateAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ view.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ });
+ rotateAnimator.start();
+ }
- public static void rotateBy(@NonNull final View view, float rotationBy) {
- view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- view.animate().rotationBy(rotationBy).setInterpolator(new FastOutSlowInInterpolator()).setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- view.setLayerType(View.LAYER_TYPE_NONE, null);
- }
- });
- }
+ public static void rotateBy(@NonNull final View view, float rotationBy) {
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ view.animate().rotationBy(rotationBy).setInterpolator(new FastOutSlowInInterpolator()).setListener(
+ new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ view.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ });
+ }
- public static void alpha(@NonNull final View convertView, float alpha, @Nullable final OnAnimationEndListener listener) {
- convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ALPHA, convertView.getAlpha(), alpha);
- rotateAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
- convertView.setVisibility(View.VISIBLE);
- }
+ public static void alpha(@NonNull final View convertView, float alpha,
+ @Nullable final OnAnimationEndListener listener) {
+ convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ALPHA, convertView.getAlpha(), alpha);
+ rotateAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ convertView.setVisibility(View.VISIBLE);
+ }
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- convertView.setLayerType(View.LAYER_TYPE_NONE, null);
- if (listener != null) {
- listener.onAnimationEnd();
- }
- }
- });
- rotateAnimator.start();
- }
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ convertView.setLayerType(View.LAYER_TYPE_NONE, null);
+ if (listener != null) {
+ listener.onAnimationEnd();
+ }
+ }
+ });
+ rotateAnimator.start();
+ }
- public static void alpha(@NonNull final View convertView, float alpha) {
- alpha(convertView, alpha, null);
- }
+ public static void alpha(@NonNull final View convertView, float alpha) {
+ alpha(convertView, alpha, null);
+ }
- public interface OnAnimationEndListener {
- void onAnimationEnd();
- }
+ public interface OnAnimationEndListener {
+ void onAnimationEnd();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java
index 190e0b9b8f..d45d647247 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java
@@ -19,101 +19,104 @@ import java.util.regex.Pattern;
public class ColorUtils {
- /**
- * Returns a color integer associated as primary color from a theme based on a {@link Context}.
- *
- * @param context The context used to style the color attributes.
- * @return The primary color value of current theme in the form 0xAARRGGBB.
- */
- @ColorInt
- public static int getPrimaryColor(@NonNull Context context) {
- TypedValue typedValue = new TypedValue();
- Resources.Theme theme = context.getTheme();
- theme.resolveAttribute(R.attr.colorPrimary, typedValue, true);
- return typedValue.data;
- }
+ /**
+ * Returns a color integer associated as primary color from a theme based on a {@link Context}.
+ *
+ * @param context The context used to style the color attributes.
+ * @return The primary color value of current theme in the form 0xAARRGGBB.
+ */
+ @ColorInt
+ public static int getPrimaryColor(@NonNull Context context) {
+ TypedValue typedValue = new TypedValue();
+ Resources.Theme theme = context.getTheme();
+ theme.resolveAttribute(R.attr.colorPrimary, typedValue, true);
+ return typedValue.data;
+ }
- /**
- * Returns a color integer associated as primary dark color from a theme based on a {@link Context}.
- *
- * @param context The context used to style the color attributes.
- * @return The primary dark color value of current theme in the form 0xAARRGGBB.
- */
- @ColorInt
- public static int getPrimaryDarkColor(@NonNull Context context) {
- TypedValue typedValue = new TypedValue();
- Resources.Theme theme = context.getTheme();
- theme.resolveAttribute(R.attr.colorPrimaryDark, typedValue, true);
- return typedValue.data;
- }
+ /**
+ * Returns a color integer associated as primary dark color from a theme based on a {@link Context}.
+ *
+ * @param context The context used to style the color attributes.
+ * @return The primary dark color value of current theme in the form 0xAARRGGBB.
+ */
+ @ColorInt
+ public static int getPrimaryDarkColor(@NonNull Context context) {
+ TypedValue typedValue = new TypedValue();
+ Resources.Theme theme = context.getTheme();
+ theme.resolveAttribute(R.attr.colorPrimaryDark, typedValue, true);
+ return typedValue.data;
+ }
- /**
- * Returns a color integer associated as accent color from a theme based on a {@link Context}.
- *
- * @param context The context used to style the color attributes.
- * @return The accent color value of current theme in the form 0xAARRGGBB.
- */
- @ColorInt
- public static int getAccentColor(@NonNull Context context) {
- TypedValue typedValue = new TypedValue();
- Resources.Theme theme = context.getTheme();
- theme.resolveAttribute(R.attr.colorAccent, typedValue, true);
- return typedValue.data;
- }
+ /**
+ * Returns a color integer associated as accent color from a theme based on a {@link Context}.
+ *
+ * @param context The context used to style the color attributes.
+ * @return The accent color value of current theme in the form 0xAARRGGBB.
+ */
+ @ColorInt
+ public static int getAccentColor(@NonNull Context context) {
+ TypedValue typedValue = new TypedValue();
+ Resources.Theme theme = context.getTheme();
+ theme.resolveAttribute(R.attr.colorAccent, typedValue, true);
+ return typedValue.data;
+ }
- /**
- * Returns a color state list associated with a theme based on a {@link Context}
- *
- * @param color The color used for tinting.
- * @return A ColorStateList object containing the primary color of a theme
- */
- @NonNull
- public static ColorStateList getSelector(@ColorInt int color) {
- return new ColorStateList(
- new int[][]{
- new int[]{android.R.attr.state_pressed},
- new int[]{}
- },
- new int[]{
- color,
- color
- }
- );
- }
+ /**
+ * Returns a color state list associated with a theme based on a {@link Context}
+ *
+ * @param color The color used for tinting.
+ * @return A ColorStateList object containing the primary color of a theme
+ */
+ @NonNull
+ public static ColorStateList getSelector(@ColorInt int color) {
+ return new ColorStateList(
+ new int[][] {
+ new int[] {android.R.attr.state_pressed},
+ new int[] {}
+ },
+ new int[] {
+ color,
+ color
+ }
+ );
+ }
- /**
- * Set a color tint list to the {@link Drawable} of an {@link ImageView}.
- *
- * @param imageView The view to set the default tint list.
- * @param tintColor The color to tint.
- */
- public static void setTintList(@NonNull ImageView imageView, @ColorInt int tintColor) {
- Drawable originalDrawable = imageView.getDrawable();
- Drawable wrappedDrawable = DrawableCompat.wrap(originalDrawable);
- DrawableCompat.setTintList(wrappedDrawable, getSelector(tintColor));
- }
+ /**
+ * Set a color tint list to the {@link Drawable} of an {@link ImageView}.
+ *
+ * @param imageView The view to set the default tint list.
+ * @param tintColor The color to tint.
+ */
+ public static void setTintList(@NonNull ImageView imageView, @ColorInt int tintColor) {
+ Drawable originalDrawable = imageView.getDrawable();
+ Drawable wrappedDrawable = DrawableCompat.wrap(originalDrawable);
+ DrawableCompat.setTintList(wrappedDrawable, getSelector(tintColor));
+ }
- static int normalizeColorComponent(String value) {
- return (int) (Float.parseFloat(value) * 255);
- }
+ static int normalizeColorComponent(String value) {
+ return (int) (Float.parseFloat(value) * 255);
+ }
- /**
- * Convert an rgba string to a Color int.
- *
- * @param value the String representation of rgba
- * @return the int representation of rgba
- * @throws ConversionException on illegal input
- */
- @ColorInt
- public static int rgbaToColor(String value) {
- Pattern c = Pattern.compile("rgba?\\s*\\(\\s*(\\d+\\.?\\d*)\\s*,\\s*(\\d+\\.?\\d*)\\s*,\\s*(\\d+\\.?\\d*)\\s*,?\\s*(\\d+\\.?\\d*)?\\s*\\)");
- Matcher m = c.matcher(value);
- if (m.matches() && m.groupCount() == 3) {
- return Color.rgb(normalizeColorComponent(m.group(1)), normalizeColorComponent(m.group(2)), normalizeColorComponent(m.group(3)));
- } else if (m.matches() && m.groupCount() == 4) {
- return Color.argb(normalizeColorComponent(m.group(4)), normalizeColorComponent(m.group(1)), normalizeColorComponent(m.group(2)), normalizeColorComponent(m.group(3)));
- } else {
- throw new ConversionException("Not a valid rgb/rgba value");
- }
+ /**
+ * Convert an rgba string to a Color int.
+ *
+ * @param value the String representation of rgba
+ * @return the int representation of rgba
+ * @throws ConversionException on illegal input
+ */
+ @ColorInt
+ public static int rgbaToColor(String value) {
+ Pattern c = Pattern.compile("rgba?\\s*\\(\\s*(\\d+\\.?\\d*)\\s*,\\s*(\\d+\\.?\\d*)\\s*,\\s*(\\d+\\.?\\d*)\\s*,"
+ + "?\\s*(\\d+\\.?\\d*)?\\s*\\)");
+ Matcher m = c.matcher(value);
+ if (m.matches() && m.groupCount() == 3) {
+ return Color.rgb(normalizeColorComponent(m.group(1)), normalizeColorComponent(m.group(2)),
+ normalizeColorComponent(m.group(3)));
+ } else if (m.matches() && m.groupCount() == 4) {
+ return Color.argb(normalizeColorComponent(m.group(4)), normalizeColorComponent(m.group(1)),
+ normalizeColorComponent(m.group(2)), normalizeColorComponent(m.group(3)));
+ } else {
+ throw new ConversionException("Not a valid rgb/rgba value");
}
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MapFragmentUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MapFragmentUtils.java
new file mode 100644
index 0000000000..f810d6231d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MapFragmentUtils.java
@@ -0,0 +1,56 @@
+package com.mapbox.mapboxsdk.utils;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.support.v4.content.ContextCompat;
+
+import com.mapbox.mapboxsdk.R;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
+
+/**
+ * MapFragment utility class.
+ * <p>
+ * Used to extract duplicate code between {@link com.mapbox.mapboxsdk.maps.MapFragment} and
+ * {@link com.mapbox.mapboxsdk.maps.SupportMapFragment}.
+ * </p>
+ */
+public class MapFragmentUtils {
+
+ public static Bundle createFragmentArgs(MapboxMapOptions options) {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS, options);
+ return bundle;
+ }
+
+ public static MapboxMapOptions resolveArgs(Context context, Bundle args) {
+ MapboxMapOptions options;
+ if (args != null && args.containsKey(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS)) {
+ options = args.getParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS);
+ } else {
+ // load default options
+ options = MapboxMapOptions.createFromAttributes(context, null);
+ }
+ options = loadDefaultMyLocationViewDrawables(context, options);
+ return options;
+ }
+
+ private static MapboxMapOptions loadDefaultMyLocationViewDrawables(Context context, MapboxMapOptions options) {
+ Drawable foregroundDrawable = options.getMyLocationForegroundDrawable();
+ Drawable foregroundBearingDrawable = options.getMyLocationForegroundBearingDrawable();
+ if (foregroundDrawable == null || foregroundBearingDrawable == null) {
+ if (foregroundDrawable == null) {
+ foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_default);
+ }
+ if (foregroundBearingDrawable == null) {
+ foregroundBearingDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_bearing);
+ }
+ options.myLocationForegroundDrawables(foregroundDrawable, foregroundBearingDrawable);
+ }
+ if (options.getMyLocationBackgroundDrawable() == null) {
+ options.myLocationBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_bg_shape));
+ }
+ return options;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java
index a92999c0d5..30ec214798 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java
@@ -2,45 +2,65 @@ package com.mapbox.mapboxsdk.utils;
public class MathUtils {
- /**
- * Test a value in specified range, returning minimum if it's below, and maximum if it's above
- * @param value Value to test
- * @param min Minimum value of range
- * @param max Maximum value of range
- * @return value if it's between min and max, min if it's below, max if it's above
- */
- public static double clamp(double value, double min, double max) {
- return Math.max(min, Math.min(max, value));
- }
+ /**
+ * Test a value in specified range, returning minimum if it's below, and maximum if it's above
+ *
+ * @param value Value to test
+ * @param min Minimum value of range
+ * @param max Maximum value of range
+ * @return value if it's between min and max, min if it's below, max if it's above
+ */
+ public static double clamp(double value, double min, double max) {
+ return Math.max(min, Math.min(max, value));
+ }
- /**
- * Test a value in specified range, returning minimum if it's below, and maximum if it's above
- * @param value Value to test
- * @param min Minimum value of range
- * @param max Maximum value of range
- * @return value if it's between min and max, min if it's below, max if it's above
- */
- public static float clamp(float value, float min, float max) {
- return Math.max(min, Math.min(max, value));
- }
+ /**
+ * Test a value in specified range, returning minimum if it's below, and maximum if it's above
+ *
+ * @param value Value to test
+ * @param min Minimum value of range
+ * @param max Maximum value of range
+ * @return value if it's between min and max, min if it's below, max if it's above
+ */
+ public static float clamp(float value, float min, float max) {
+ return Math.max(min, Math.min(max, value));
+ }
+
+ /**
+ * Constrains value to the given range (including min, excluding max) via modular arithmetic.
+ * <p>
+ * Same formula as used in Core GL (wrap.hpp)
+ * std::fmod((std::fmod((value - min), d) + d), d) + min;
+ *
+ * @param value Value to wrap
+ * @param min Minimum value
+ * @param max Maximum value
+ * @return Wrapped value
+ */
+ public static double wrap(double value, double min, double max) {
+ double delta = max - min;
+
+ double firstMod = (value - min) % delta;
+ double secondMod = (firstMod + delta) % delta;
- /**
- * Constrains value to the given range (including min, excluding max) via modular arithmetic.
- *
- * Same formula as used in Core GL (wrap.hpp)
- * std::fmod((std::fmod((value - min), d) + d), d) + min;
- *
- * @param value Value to wrap
- * @param min Minimum value
- * @param max Maximum value
- * @return Wrapped value
- */
- public static double wrap(double value, double min, double max) {
- double delta = max - min;
-
- double firstMod = (value - min) % delta;
- double secondMod = (firstMod + delta) % delta;
-
- return secondMod + min;
+ return secondMod + min;
+ }
+
+ /**
+ * Convert bearing from core to match Android SDK value.
+ *
+ * @param nativeBearing bearing value coming from core
+ * @return bearing in degrees starting from 0 rotating clockwise
+ */
+ public static double convertNativeBearing(double nativeBearing) {
+ double direction = -nativeBearing;
+
+ while (direction > 360) {
+ direction -= 360;
+ }
+ while (direction < 0) {
+ direction += 360;
}
+ return direction;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
index 4fbf3d5fe1..5b2945d55d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
@@ -1,57 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <!--Add references to exposed resources-->
- <public name="AttributionAlertDialogStyle" type="style" />
-
- <public name="style_mapbox_streets" type="string" />
- <public name="style_emerald" type="string" />
- <public name="style_light" type="string" />
- <public name="style_dark" type="string" />
- <public name="style_satellite" type="string" />
- <public name="style_satellite_streets" type="string" />
-
- <public name="center_longitude" type="attr" />
- <public name="center_latitude" type="attr" />
- <public name="zoom_level" type="attr" />
- <public name="direction" type="attr" />
- <public name="zoom_enabled" type="attr" />
- <public name="scroll_enabled" type="attr" />
- <public name="rotate_enabled" type="attr" />
- <public name="zoom_controls_enabled" type="attr" />
- <public name="debug_active" type="attr" />
- <public name="style_url" type="attr" />
- <public name="access_token" type="attr" />
- <public name="style_classes" type="attr" />
- <public name="my_location_enabled" type="attr" />
- <public name="compass_enabled" type="attr" />
- <public name="compass_gravity" type="attr" />
- <public name="compass_margin_left" type="attr" />
- <public name="compass_margin_top" type="attr" />
- <public name="compass_margin_right" type="attr" />
- <public name="compass_margin_bottom" type="attr" />
- <public name="compass_fade_facing_north" type="attr" />
- <public name="logo_gravity" type="attr" />
- <public name="logo_margin_left" type="attr" />
- <public name="logo_margin_top" type="attr" />
- <public name="logo_margin_right" type="attr" />
- <public name="logo_margin_bottom" type="attr" />
- <public name="logo_visibility" type="attr" />
- <public name="attribution_gravity" type="attr" />
- <public name="attribution_margin_left" type="attr" />
- <public name="attribution_margin_top" type="attr" />
- <public name="attribution_margin_right" type="attr" />
- <public name="attribution_margin_bottom" type="attr" />
- <public name="attribution_visibility" type="attr" />
-
- <public name="attribution_logo" type="drawable" />
- <public name="compass" type="drawable" />
- <public name="default_marker" type="drawable" />
- <public name="attribution_button_pressed_selector" type="drawable" />
- <public name="attribution_button_pressed_normal" type="drawable" />
- <public name="attribution_button_pressed_pressed" type="drawable" />
- <public name="my_location" type="drawable" />
- <public name="my_location_bearing" type="drawable" />
- <public name="my_location_stale" type="drawable" />
- <public name="my_location_ring" type="color" />
+
+ <!-- This file contains attributes and styles that are part of the public API-->
+ <!-- Users can find these with code completion while other ones from this module will remain-->
+ <!-- hidden, though the user can reference them but won't show up during code completion-->
+
+ <public name="mapbox_AlertDialogStyle" type="style" />
+
+ <!-- Exposed attrs.xml -->
+ <public name="mapbox_accessToken" type="attr" />
+ <public name="mapbox_styleUrl" type="attr" />
+ <public name="mapbox_apiBaseUrl" type="attr" />
+
+ <public name="mapbox_cameraTargetLng" type="attr" />
+ <public name="mapbox_cameraTargetLat" type="attr" />
+ <public name="mapbox_cameraZoom_level" type="attr" />
+ <public name="mapbox_cameraBearing" type="attr" />
+
+ <public name="mapbox_uiZoomGestures" type="attr" />
+ <public name="mapbox_uiScrollGestures" type="attr" />
+ <public name="mapbox_uiRotateGestures" type="attr" />
+ <public name="mapbox_uiZoomControls" type="attr" />
+
+ <public name="mapbox_myLocation" type="attr" />
+ <public name="mapbox_myLocationTintColor" type="attr" />
+ <public name="mapbox_myLocationDrawable" type="attr" />
+ <public name="mapbox_myLocationBearingDrawable" type="attr" />
+ <public name="mapbox_myLocationBackgroundDrawable" type="attr" />
+ <public name="mapbox_myLocationBackgroundTintColor" type="attr" />
+ <public name="mapbox_myLocationBackgroundMarginLeft" type="attr" />
+ <public name="mapbox_myLocationBackgroundMarginTop" type="attr" />
+ <public name="mapbox_myLocationBackgroundMarginRight" type="attr" />
+ <public name="mapbox_myLocationBackgroundMarginBottom" type="attr" />
+ <public name="mapbox_myLocationAccuracyTintColor" type="attr" />
+ <public name="mapbox_myLocationAccuracyAlpha" type="attr" />
+
+ <public name="mapbox_uiCompass" type="attr" />
+ <public name="mapbox_uiCompassGravity" type="attr" />
+ <public name="mapbox_uiCompassMarginLeft" type="attr" />
+ <public name="mapbox_uiCompassMarginTop" type="attr" />
+ <public name="mapbox_uiCompassMarginRight" type="attr" />
+ <public name="mapbox_uiCompassMarginBottom" type="attr" />
+ <public name="mapbox_uiCompassFadeFacingNorth" type="attr" />
+
+ <public name="mapbox_uiLogo" type="attr" />
+ <public name="mapbox_uiLogoGravity" type="attr" />
+ <public name="mapbox_uiLogoMarginLeft" type="attr" />
+ <public name="mapbox_uiLogoMarginTop" type="attr" />
+ <public name="mapbox_uiLogoMarginRight" type="attr" />
+ <public name="mapbox_uiLogoMarginBottom" type="attr" />
+
+ <public name="mapbox_uiAttribution" type="attr" />
+ <public name="mapbox_uiAttributionGravity" type="attr" />
+ <public name="mapbox_uiAttributionMarginLeft" type="attr" />
+ <public name="mapbox_uiAttributionMarginTop" type="attr" />
+ <public name="mapbox_uiAttributionMarginRight" type="attr" />
+ <public name="mapbox_uiAttributionMarginBottom" type="attr" />
+
+ <public name="mapbox_renderTextureMode" type="attr" />
+
+ <!-- Exposed styles -->
+ <public name="mapbox_style_mapbox_streets" type="string" />
+ <public name="mapbox_style_emerald" type="string" />
+ <public name="mapbox_style_light" type="string" />
+ <public name="mapbox_style_dark" type="string" />
+ <public name="mapbox_style_satellite" type="string" />
+ <public name="mapbox_style_satellite_streets" type="string" />
+
+ <!-- Exposed drawables -->
+ <public name="mapbox_logo_icon" type="drawable" />
+ <public name="mapbox_compass_icon" type="drawable" />
+ <public name="mapbox_marker_icon_default" type="drawable" />
+ <public name="mapbox_info_bg_selector" type="drawable" />
+ <public name="mapbox_info_icon_default" type="drawable" />
+ <public name="mapbox_info_icon_selected" type="drawable" />
+ <public name="mapbox_mylocation_icon_default" type="drawable" />
+ <public name="mapbox_mylocation_icon_bearing" type="drawable" />
+
+ <!-- Exposed colors -->
+ <public name="mapbox_mylocation_ring" type="color" />
<public name="mapbox_blue" type="color" />
</resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/color/material_bg_selector.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/color/mapbox_material_bg_selector.xml
index 64d7f46c2d..64d7f46c2d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/color/material_bg_selector.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/color/mapbox_material_bg_selector.xml
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/compass.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_compass_icon.png
index 6bb20027f4..6bb20027f4 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/compass.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_compass_icon.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/attribution_logo.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_logo_icon.png
index c0f4ed2c4c..c0f4ed2c4c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/attribution_logo.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_logo_icon.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/default_marker.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_marker_icon_default.png
index 8b0af4c6ab..8b0af4c6ab 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/default_marker.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_marker_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/default_markerview.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_markerview_icon_default.png
index 651482f3ee..651482f3ee 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/default_markerview.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_markerview_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_mylocation_icon_bearing.png
index c93fa4781a..c93fa4781a 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_bearing.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_mylocation_icon_bearing.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_normal.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_mylocation_icon_default.png
index 120b7dd612..120b7dd612 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_normal.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_mylocation_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/compass.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_compass_icon.png
index cf15ed1876..cf15ed1876 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/compass.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_compass_icon.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/attribution_logo.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_logo_icon.png
index 5a9da3fe39..5a9da3fe39 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/attribution_logo.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_logo_icon.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/default_marker.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_marker_icon_default.png
index b112096c18..b112096c18 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/default_marker.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_marker_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/default_markerview.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_markerview_icon_default.png
index 63cb7b5f4b..63cb7b5f4b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/default_markerview.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_markerview_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_mylocation_icon_bearing.png
index 0d7d89a8b4..0d7d89a8b4 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_bearing.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_mylocation_icon_bearing.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_normal.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_mylocation_icon_default.png
index 831ef1acf4..831ef1acf4 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_normal.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_mylocation_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-v21/bg_default_selector.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-v21/mapbox_default_bg_selector.xml
index ef82c18f5d..ef82c18f5d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-v21/bg_default_selector.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-v21/mapbox_default_bg_selector.xml
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/compass.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_compass_icon.png
index 6257209368..6257209368 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/compass.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_compass_icon.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/attribution_logo.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_logo_icon.png
index 194aa64da2..194aa64da2 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/attribution_logo.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_logo_icon.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/default_marker.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_marker_icon_default.png
index d05c82bfe2..d05c82bfe2 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/default_marker.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_marker_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/default_markerview.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_markerview_icon_default.png
index 175f88ff88..175f88ff88 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/default_markerview.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_markerview_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_mylocation_icon_bearing.png
index 1056d617e9..1056d617e9 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_bearing.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_mylocation_icon_bearing.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_normal.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_mylocation_icon_default.png
index 37b1f7adbf..37b1f7adbf 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_normal.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_mylocation_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/compass.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_compass_icon.png
index c59b4c7528..c59b4c7528 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/compass.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_compass_icon.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/attribution_logo.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_logo_icon.png
index d1260a16f3..d1260a16f3 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/attribution_logo.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_logo_icon.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapview_preview.jpg b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_mapview_preview.jpg
index 3a21fc08bc..3a21fc08bc 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapview_preview.jpg
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_mapview_preview.jpg
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/default_marker.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_marker_icon_default.png
index 703b172c15..703b172c15 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/default_marker.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_marker_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/default_markerview.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_markerview_icon_default.png
index be782e1d4b..be782e1d4b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/default_markerview.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_markerview_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_mylocation_icon_bearing.png
index 1ff2590606..1ff2590606 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_bearing.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_mylocation_icon_bearing.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_normal.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_mylocation_icon_default.png
index 520b85eff7..520b85eff7 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_normal.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_mylocation_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/compass.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_compass_icon.png
index da04f5b94c..da04f5b94c 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/compass.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_compass_icon.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/bg_infowindow_content.9.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_infowindow_icon_bg.9.png
index 584b320299..584b320299 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/bg_infowindow_content.9.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_infowindow_icon_bg.9.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/attribution_logo.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_logo_icon.png
index 5f9647610a..5f9647610a 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/attribution_logo.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_logo_icon.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/default_marker.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_marker_icon_default.png
index 8331ffef71..8331ffef71 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/default_marker.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_marker_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/default_markerview.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_markerview_icon_default.png
index fe1c486518..fe1c486518 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/default_markerview.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_markerview_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_mylocation_icon_bearing.png
index 671c33a08e..671c33a08e 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_bearing.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_mylocation_icon_bearing.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_normal.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_mylocation_icon_default.png
index f9f4265d2a..f9f4265d2a 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_normal.png
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_mylocation_icon_default.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/bg_default_selector.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/bg_default_selector.xml
deleted file mode 100644
index 48e53e7ee8..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/bg_default_selector.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@color/gray_light" android:state_pressed="true" />
- <item android:drawable="@color/gray_light" android:state_focused="true" />
- <item android:drawable="@android:color/transparent" />
-</selector> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_info_outline_24dp_selector.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_info_outline_24dp_selector.xml
deleted file mode 100644
index 7f6245b30a..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_info_outline_24dp_selector.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/ic_info_outline_24dp_selected" android:state_pressed="true" />
- <item android:drawable="@drawable/ic_info_outline_24dp" />
-</selector> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_mylocationview_background.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_mylocationview_background.xml
deleted file mode 100644
index e1df60788e..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_mylocationview_background.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
-
- <solid android:color="@color/white" />
-
- <size
- android:width="@dimen/my_locationview_outer_circle"
- android:height="@dimen/my_locationview_outer_circle" />
-</shape> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_default_bg_selector.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_default_bg_selector.xml
new file mode 100644
index 0000000000..45073bb1f3
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_default_bg_selector.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@color/mapbox_gray_light" android:state_pressed="true" />
+ <item android:drawable="@color/mapbox_gray_light" android:state_focused="true" />
+ <item android:drawable="@android:color/transparent" />
+</selector> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_bg_selector.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_bg_selector.xml
new file mode 100644
index 0000000000..3ead19b781
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_bg_selector.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/mapbox_info_icon_selected" android:state_pressed="true" />
+ <item android:drawable="@drawable/mapbox_info_icon_default" />
+</selector> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_info_outline_24dp.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_icon_default.xml
index fa82bb8d9b..fa82bb8d9b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_info_outline_24dp.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_icon_default.xml
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_info_outline_24dp_selected.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_icon_selected.xml
index 074928d05a..074928d05a 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_info_outline_24dp_selected.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_icon_selected.xml
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_mylocation_bg_shape.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_mylocation_bg_shape.xml
new file mode 100644
index 0000000000..df0687bbd3
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_mylocation_bg_shape.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+
+ <solid android:color="@android:color/white" />
+
+ <size
+ android:width="@dimen/mapbox_my_locationview_outer_circle"
+ android:height="@dimen/mapbox_my_locationview_outer_circle" />
+</shape> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/attribution_list_item.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_attribution_list_item.xml
index 763bb118e0..763bb118e0 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/attribution_list_item.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_attribution_list_item.xml
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/infowindow_content.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_infowindow_content.xml
index 3e36cbf91a..e1673902ef 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/infowindow_content.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_infowindow_content.xml
@@ -5,7 +5,7 @@
android:id="@+id/infowindow_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:background="@drawable/bg_infowindow_content"
+ android:background="@drawable/mapbox_infowindow_icon_bg"
android:orientation="vertical"
android:paddingBottom="16dp"
android:paddingLeft="20dp"
@@ -18,8 +18,8 @@
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:maxEms="17"
- android:text="@string/infoWindowTitle"
- android:textColor="@color/black"
+ android:text="@string/mapbox_infoWindowTitle"
+ android:textColor="@android:color/black"
android:textSize="18sp"
android:textStyle="bold" />
@@ -31,8 +31,8 @@
android:layout_marginTop="2dp"
android:lineSpacingExtra="1dp"
android:maxEms="17"
- android:text="@string/infoWindowDescription"
- android:textColor="@color/gray"
+ android:text="@string/mapbox_infoWindowDescription"
+ android:textColor="@color/mapbox_gray"
android:textSize="14sp" />
<TextView
@@ -40,15 +40,15 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxEms="17"
- android:text="@string/infoWindowAddress"
- android:textColor="@color/black"
+ android:text="@string/mapbox_infoWindowAddress"
+ android:textColor="@android:color/black"
android:textSize="12sp"
android:visibility="gone" />
</LinearLayout>
<com.mapbox.mapboxsdk.annotations.InfoWindowTipView
android:id="@+id/infowindow_tipview"
- android:layout_width="@dimen/infowindow_tipview_width"
+ android:layout_width="@dimen/mapbox_infowindow_tipview_width"
android:layout_height="14dp"
android:layout_below="@+id/infowindow_content" />
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/infowindow_view.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_infowindow_view.xml
index ff47642426..ff47642426 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/infowindow_view.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_infowindow_view.xml
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_internal.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
index 4f032c1008..c6dcd35a2f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_internal.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
@@ -27,18 +27,18 @@
android:id="@+id/logoView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:contentDescription="@string/mapboxIconContentDescription"
- android:src="@drawable/attribution_logo" />
+ android:contentDescription="@string/mapbox_iconContentDescription"
+ android:src="@drawable/mapbox_logo_icon" />
<ImageView
android:id="@+id/attributionView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
- android:background="@drawable/bg_default_selector"
+ android:background="@drawable/mapbox_default_bg_selector"
android:clickable="true"
- android:contentDescription="@string/attributionsIconContentDescription"
+ android:contentDescription="@string/mapbox_attributionsIconContentDescription"
android:padding="7dp"
- android:src="@drawable/ic_info_outline_24dp_selector" />
+ android:src="@drawable/mapbox_info_bg_selector" />
</merge> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_preview.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_preview.xml
index d8f2193fd5..5517c0cfe6 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_preview.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_preview.xml
@@ -8,34 +8,34 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
- android:src="@drawable/mapview_preview" />
+ android:src="@drawable/mapbox_mapview_preview" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
- android:layout_marginBottom="@dimen/eight_dp"
- android:layout_marginLeft="@dimen/eight_dp"
- android:contentDescription="@string/mapboxIconContentDescription"
- android:src="@drawable/attribution_logo" />
+ android:layout_marginBottom="@dimen/mapbox_eight_dp"
+ android:layout_marginLeft="@dimen/mapbox_eight_dp"
+ android:contentDescription="@string/mapbox_iconContentDescription"
+ android:src="@drawable/mapbox_logo_icon" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
- android:layout_marginBottom="@dimen/seven_dp"
- android:layout_marginLeft="@dimen/seventy_six_dp"
- android:background="@drawable/bg_default_selector"
+ android:layout_marginBottom="@dimen/mapbox_seven_dp"
+ android:layout_marginLeft="@dimen/mapbox_seventy_six_dp"
+ android:background="@drawable/mapbox_default_bg_selector"
android:clickable="true"
- android:contentDescription="@string/attributionsIconContentDescription"
- android:src="@drawable/ic_info_outline_24dp_selector" />
+ android:contentDescription="@string/mapbox_attributionsIconContentDescription"
+ android:src="@drawable/mapbox_info_bg_selector" />
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentRight="true"
android:layout_margin="10dp"
- android:src="@drawable/compass" />
+ android:src="@drawable/mapbox_compass_icon" />
</RelativeLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/view_image_marker.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_view_image_marker.xml
index 7e4a079063..7e4a079063 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/view_image_marker.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_view_image_marker.xml
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/arrays.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/arrays.xml
index bb466880aa..5a5fd6cb4c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/arrays.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/arrays.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <array name="attribution_names">
+ <array name="mapbox_attribution_names">
<item>&#169; Mapbox</item>
<item>&#169; OpenStreetMap</item>
<item>Improve this map</item>
<item>Telemetry Settings</item>
</array>
<!-- If editing this array update MapView.ATTRIBUTION_INDEX_IMPROVE_THIS_MAP -->
- <array name="attribution_links" formatted="false" translatable="false">
+ <array name="mapbox_attribution_links" formatted="false" translatable="false">
<item>https://www.mapbox.com/about/maps/</item>
<item>http://www.openstreetmap.org/about/</item>
<item>https://www.mapbox.com/map-feedback/#/%1$f/%2$f/%3$d</item>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
index 458056c14e..12c395d46f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
@@ -1,50 +1,48 @@
<resources>
<!-- these are public -->
- <declare-styleable name="MapView">
+ <declare-styleable name="mapbox_MapView">
<!--Configuration-->
- <attr name="access_token" format="string" />
- <attr name="style_url" format="string" />
- <attr name="api_base_url" format="string" />
+ <attr name="mapbox_styleUrl" format="string" />
+ <attr name="mapbox_apiBaseUrl" format="string" />
<!--Camera-->
- <attr name="center_longitude" format="float" />
- <attr name="center_latitude" format="float" />
- <attr name="zoom" format="float" />
- <attr name="direction" format="float" />
- <attr name="tilt" format="float" />
+ <attr name="mapbox_cameraTargetLat" format="float" />
+ <attr name="mapbox_cameraTargetLng" format="float" />
+ <attr name="mapbox_cameraZoom" format="float" />
+ <attr name="mapbox_cameraBearing" format="float" />
+ <attr name="mapbox_cameraTilt" format="float" />
<!--Zoom-->
- <attr name="zoom_max" format="float" />
- <attr name="zoom_min" format="float" />
+ <attr name="mapbox_cameraZoomMax" format="float" />
+ <attr name="mapbox_cameraZoomMin" format="float" />
<!--Gestures-->
- <attr name="zoom_enabled" format="boolean" />
- <attr name="scroll_enabled" format="boolean" />
- <attr name="rotate_enabled" format="boolean" />
- <attr name="tilt_enabled" format="boolean" />
- <attr name="debug_active" format="boolean" />
+ <attr name="mapbox_uiZoomGestures" format="boolean" />
+ <attr name="mapbox_uiScrollGestures" format="boolean" />
+ <attr name="mapbox_uiRotateGestures" format="boolean" />
+ <attr name="mapbox_uiTiltGestures" format="boolean" />
<!--UI-Controls-->
- <attr name="zoom_controls_enabled" format="boolean" />
+ <attr name="mapbox_uiZoomControls" format="boolean" />
<!--MyLocation-->
- <attr name="my_location_enabled" format="boolean" />
- <attr name="my_location_foreground" format="reference" />
- <attr name="my_location_foreground_bearing" format="reference" />
- <attr name="my_location_foreground_tint" format="color" />
- <attr name="my_location_background" format="reference" />
- <attr name="my_location_background_tint" format="color" />
- <attr name="my_location_background_left" format="dimension" />
- <attr name="my_location_background_top" format="dimension" />
- <attr name="my_location_background_right" format="dimension" />
- <attr name="my_location_background_bottom" format="dimension" />
- <attr name="my_location_accuracy_tint" format="color" />
- <attr name="my_location_accuracy_alpha" format="integer" />
+ <attr name="mapbox_myLocation" format="boolean" />
+ <attr name="mapbox_myLocationTintColor" format="color" />
+ <attr name="mapbox_myLocationDrawable" format="reference" />
+ <attr name="mapbox_myLocationBearingDrawable" format="reference" />
+ <attr name="mapbox_myLocationBackgroundDrawable" format="reference" />
+ <attr name="mapbox_myLocationBackgroundTintColor" format="color" />
+ <attr name="mapbox_myLocationBackgroundMarginLeft" format="dimension" />
+ <attr name="mapbox_myLocationBackgroundMarginTop" format="dimension" />
+ <attr name="mapbox_myLocationBackgroundMarginRight" format="dimension" />
+ <attr name="mapbox_myLocationBackgroundMarginBottom" format="dimension" />
+ <attr name="mapbox_myLocationAccuracyTintColor" format="color" />
+ <attr name="mapbox_myLocationAccuracyAlpha" format="integer" />
<!--Compass-->
- <attr name="compass_enabled" format="boolean" />
- <attr name="compass_gravity">
+ <attr name="mapbox_uiCompass" format="boolean" />
+ <attr name="mapbox_uiCompassGravity">
<flag name="top" value="0x30" />
<flag name="bottom" value="0x50" />
<flag name="left" value="0x03" />
@@ -60,14 +58,15 @@
<flag name="start" value="0x00800003" />
<flag name="end" value="0x00800005" />
</attr>
- <attr name="compass_margin_left" format="dimension" />
- <attr name="compass_margin_top" format="dimension" />
- <attr name="compass_margin_right" format="dimension" />
- <attr name="compass_margin_bottom" format="dimension" />
- <attr name="compass_fade_facing_north" format="boolean" />
+ <attr name="mapbox_uiCompassMarginLeft" format="dimension" />
+ <attr name="mapbox_uiCompassMarginTop" format="dimension" />
+ <attr name="mapbox_uiCompassMarginRight" format="dimension" />
+ <attr name="mapbox_uiCompassMarginBottom" format="dimension" />
+ <attr name="mapbox_uiCompassFadeFacingNorth" format="boolean" />
<!--Logo-->
- <attr name="logo_gravity">
+ <attr name="mapbox_uiLogo" format="boolean" />
+ <attr name="mapbox_uiLogoGravity">
<flag name="top" value="0x30" />
<flag name="bottom" value="0x50" />
<flag name="left" value="0x03" />
@@ -83,14 +82,14 @@
<flag name="start" value="0x00800003" />
<flag name="end" value="0x00800005" />
</attr>
- <attr name="logo_margin_left" format="dimension" />
- <attr name="logo_margin_top" format="dimension" />
- <attr name="logo_margin_right" format="dimension" />
- <attr name="logo_margin_bottom" format="dimension" />
- <attr name="logo_enabled" format="boolean" />
+ <attr name="mapbox_uiLogoMarginLeft" format="dimension" />
+ <attr name="mapbox_uiLogoMarginTop" format="dimension" />
+ <attr name="mapbox_uiLogoMarginRight" format="dimension" />
+ <attr name="mapbox_uiLogoMarginBottom" format="dimension" />
<!--Attribution-->
- <attr name="attribution_gravity">
+ <attr name="mapbox_uiAttribution" format="boolean" />
+ <attr name="mapbox_uiAttributionGravity">
<flag name="top" value="0x30" />
<flag name="bottom" value="0x50" />
<flag name="left" value="0x03" />
@@ -106,14 +105,14 @@
<flag name="start" value="0x00800003" />
<flag name="end" value="0x00800005" />
</attr>
- <attr name="attribution_margin_left" format="dimension" />
- <attr name="attribution_margin_top" format="dimension" />
- <attr name="attribution_margin_right" format="dimension" />
- <attr name="attribution_margin_bottom" format="dimension" />
- <attr name="attribution_enabled" format="boolean" />
- <attr name="attribution_tint" format="color" />
+ <attr name="mapbox_uiAttributionMarginLeft" format="dimension" />
+ <attr name="mapbox_uiAttributionMarginTop" format="dimension" />
+ <attr name="mapbox_uiAttributionMarginRight" format="dimension" />
+ <attr name="mapbox_uiAttributionMarginBottom" format="dimension" />
+ <attr name="mapbox_uiAttributionTintColor" format="color" />
<!-- Deprecated to use TextureView-->
- <attr name="texture_mode" format="boolean" />
+ <attr name="mapbox_renderTextureMode" format="boolean" />
+
</declare-styleable>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml
index 63f739c30c..63ef42c2c3 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml
@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <color name="white">#F9F9F9</color>
- <color name="black">#000000</color>
- <color name="gray">#7D7F80</color>
- <color name="gray_light">#EEEEEE</color>
+ <color name="mapbox_gray">#7D7F80</color>
+ <color name="mapbox_gray_light">#EEEEEE</color>
<color name="mapbox_blue">#1E8CAB</color>
- <color name="my_location_ring">@color/mapbox_blue</color>
+ <color name="mapbox_my_location_ring">@color/mapbox_blue</color>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
index fd0f4b98e7..31b9dd2bcd 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <dimen name="infowindow_tipview_width">20dp</dimen>
- <dimen name="infowindow_margin">8dp</dimen>
- <dimen name="infowindow_offset">-2dp</dimen>
- <dimen name="infowindow_line_width">1.5dp</dimen>
- <dimen name="seven_dp">7dp</dimen>
- <dimen name="eight_dp">8dp</dimen>
- <dimen name="ten_dp">10dp</dimen>
- <dimen name="sixteen_dp">16dp</dimen>
- <dimen name="seventy_six_dp">76dp</dimen>
- <dimen name="my_locationview_outer_circle">18dp</dimen>
+ <dimen name="mapbox_infowindow_tipview_width">20dp</dimen>
+ <dimen name="mapbox_infowindow_margin">8dp</dimen>
+ <dimen name="mapbox_infowindow_offset">-2dp</dimen>
+ <dimen name="mapbox_infowindow_line_width">1.5dp</dimen>
+ <dimen name="mapbox_seven_dp">7dp</dimen>
+ <dimen name="mapbox_eight_dp">8dp</dimen>
+ <dimen name="mapbox_ten_dp">10dp</dimen>
+ <dimen name="mapbox_sixteen_dp">16dp</dimen>
+ <dimen name="mapbox_seventy_six_dp">76dp</dimen>
+ <dimen name="mapbox_my_locationview_outer_circle">18dp</dimen>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/integers.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/integers.xml
deleted file mode 100644
index 3727365659..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/integers.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <integer name="style_version">9</integer>
-</resources> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml
index c8bb9d65ba..f15979efc1 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml
@@ -1,27 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="compassContentDescription">Map compass. Click to reset the map rotation to North.</string>
- <string name="attributionsIconContentDescription">Attribution icon. Click to show attribution dialog.</string>
- <string name="attributionsDialogTitle">Mapbox Android SDK</string>
- <string name="attributionTelemetryTitle">Make Mapbox Maps Better</string>
- <string name="attributionTelemetryMessage">You are helping to make OpenStreetMap and Mapbox maps better by contributing anonymous usage data.</string>
- <string name="attributionTelemetryPositive">Agree</string>
- <string name="attributionTelemetryNegative">Disagree</string>
- <string name="attributionTelemetryNeutral">More info</string>
- <string name="mapboxIconContentDescription">The Mapbox logo.</string>
- <string name="infoWindowTitle">Title</string>
- <string name="infoWindowDescription">Description</string>
- <string name="infoWindowAddress">Address</string>
+ <string name="mapbox_compassContentDescription">Map compass. Click to reset the map rotation to North.</string>
+ <string name="mapbox_attributionsIconContentDescription">Attribution icon. Click to show attribution dialog.</string>
+ <string name="mapbox_attributionsDialogTitle">Mapbox Android SDK</string>
+ <string name="mapbox_attributionTelemetryTitle">Make Mapbox Maps Better</string>
+ <string name="mapbox_attributionTelemetryMessage">You are helping to make OpenStreetMap and Mapbox maps better by contributing anonymous usage data.</string>
+ <string name="mapbox_attributionTelemetryPositive">Agree</string>
+ <string name="mapbox_attributionTelemetryNegative">Disagree</string>
+ <string name="mapbox_attributionTelemetryNeutral">More info</string>
+ <string name="mapbox_iconContentDescription">The Mapbox logo.</string>
+ <string name="mapbox_infoWindowTitle">Title</string>
+ <string name="mapbox_infoWindowDescription">Description</string>
+ <string name="mapbox_infoWindowAddress">Address</string>
<!-- these are public -->
<!-- Using one of these constants means your map style will always use the latest version and
may change as we improve the style. -->
- <string name="style_mapbox_streets">mapbox://styles/mapbox/streets-v9</string>
- <string name="style_outdoors">mapbox://styles/mapbox/outdoors-v9</string>
+ <string name="mapbox_style_mapbox_streets">mapbox://styles/mapbox/streets-v9</string>
+ <string name="mapbox_style_outdoors">mapbox://styles/mapbox/outdoors-v9</string>
<!-- Note: Emerald style has been deprecated and will be removed in a future release-->
- <string name="style_emerald">mapbox://styles/mapbox/emerald-v8</string>
- <string name="style_light">mapbox://styles/mapbox/light-v9</string>
- <string name="style_dark">mapbox://styles/mapbox/dark-v9</string>
- <string name="style_satellite">mapbox://styles/mapbox/satellite-v9</string>
- <string name="style_satellite_streets">mapbox://styles/mapbox/satellite-streets-v9</string>
+ <string name="mapbox_style_emerald">mapbox://styles/mapbox/emerald-v8</string>
+ <string name="mapbox_style_light">mapbox://styles/mapbox/light-v9</string>
+ <string name="mapbox_style_dark">mapbox://styles/mapbox/dark-v9</string>
+ <string name="mapbox_style_satellite">mapbox://styles/mapbox/satellite-v9</string>
+ <string name="mapbox_style_satellite_streets">mapbox://styles/mapbox/satellite-streets-v9</string>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml
index 708cfc72e9..82d9d1e076 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml
@@ -1,11 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <!-- these are public -->
- <style name="AttributionAlertDialogStyle" parent="Theme.AppCompat.Dialog.Alert">
- <item name="android:textColorPrimary">@android:color/white</item>
- </style>
-
- <style name="TelemAlertDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert"/>
+ <style name="mapbox_AlertDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert"/>
</resources> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
index f5f4ec3f54..318f891127 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
+++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
@@ -1,43 +1,22 @@
-apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.application'
-apply plugin: 'checkstyle'
-apply plugin: 'devicefarm'
-
-task accessToken {
- def tokenFile = new File("MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml")
- if (!tokenFile.exists()) {
- String tokenFileContents = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
- "<resources>\n" +
- " <string name=\"mapbox_access_token\">" + "$System.env.MAPBOX_ACCESS_TOKEN" + "</string>\n" +
- "</resources>"
-
- if (tokenFileContents == null) {
- throw new InvalidUserDataException("You must set the MAPBOX_ACCESS_TOKEN environment variable.")
- }
- tokenFile.write(tokenFileContents)
- }
-}
-
-gradle.projectsEvaluated {
- preBuild.dependsOn('accessToken')
-}
ext {
- supportLibVersion = '23.4.0'
+ supportLibVersion = '25.1.0'
+ espressoVersion = '2.2.2'
+ testRunnerVersion = '0.5'
+ leakCanaryVersion = '1.5'
}
android {
- compileSdkVersion 23
- buildToolsVersion "23.0.3"
+ compileSdkVersion 25
+ buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.mapbox.mapboxsdk.testapp"
minSdkVersion 15
- targetSdkVersion 23
- versionCode 9
- versionName "4.1.0"
-
- // Specify AndroidJUnitRunner as the default test instrumentation runner
+ targetSdkVersion 25
+ versionCode 11
+ versionName "5.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
@@ -65,8 +44,9 @@ android {
buildTypes {
debug {
- // run code coverage reports
testCoverageEnabled = true
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled false
@@ -88,82 +68,30 @@ dependencies {
compile "com.android.support:recyclerview-v7:${supportLibVersion}"
// Leak Canary
- debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
- releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
- testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
+ debugCompile "com.squareup.leakcanary:leakcanary-android:${leakCanaryVersion}"
+ releaseCompile "com.squareup.leakcanary:leakcanary-android-no-op:${leakCanaryVersion}"
+ testCompile "com.squareup.leakcanary:leakcanary-android-no-op:${leakCanaryVersion}"
- // Mapbox Android Services
- compile('com.mapbox.mapboxsdk:mapbox-android-services:1.3.0@aar') {
+ // Mapbox Android Services (Java component)
+ compile('com.mapbox.mapboxsdk:mapbox-java-services:2.0.0-SNAPSHOT@jar') {
transitive = true
}
// Testing dependencies
testCompile 'junit:junit:4.12'
- testCompile 'org.mockito:mockito-core:1.10.19'
- androidTestCompile "com.android.support:support-annotations:${supportLibVersion}"
- androidTestCompile 'com.android.support.test:runner:0.4.1'
- androidTestCompile 'com.android.support.test:rules:0.4.1'
- androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
+ testCompile 'org.mockito:mockito-core:2.2.27'
androidTestCompile 'com.squareup.spoon:spoon-client:1.6.2'
+ androidTestCompile "com.android.support:support-annotations:${supportLibVersion}"
+ androidTestCompile "com.android.support.test:runner:${testRunnerVersion}"
+ androidTestCompile "com.android.support.test:rules:${testRunnerVersion}"
+ androidTestCompile "com.android.support.test.espresso:espresso-core:${espressoVersion}"
+ androidTestCompile "com.android.support.test.espresso:espresso-intents:${espressoVersion}"
}
-checkstyle {
- configFile project.file('../checks.xml')
- showViolations true
-}
-
-def getAccessKeyDeviceFarm() {
- if (project.hasProperty('AWS_ACCESS_KEY_ID_DEVICE_FARM')) {
- return AWS_ACCESS_KEY_ID_DEVICE_FARM
- } else {
- println("Could not locate AWS_ACCESS_KEY_ID_DEVICE_FARM in gradle.properties")
- return ""
- }
-}
-
-def getSecretAccessKeyDeviceFarm() {
- if (project.hasProperty('AWS_SECRET_ACCESS_KEY_DEVICE_FARM')) {
- return AWS_SECRET_ACCESS_KEY_DEVICE_FARM
- } else {
- println("Could not locate AWS_SECRET_ACCESS_KEY_DEVICE_FARM in gradle.properties")
- return ""
- }
-}
-
-devicefarm {
-
- projectName "Mapbox GL Android" // required: Must already exists.
- devicePool "sanity" // optional: Defaults to "Top Devices"
-
- authentication {
- accessKey getAccessKeyDeviceFarm()
- secretKey getSecretAccessKeyDeviceFarm()
- }
-
- devicestate {
- wifi "on"
- bluetooth "off"
- gps "on"
- nfc "on"
- latitude 47.6204 // default
- longitude - 122.3491 // default
- }
-
- instrumentation {
-
- }
-}
-
-android.applicationVariants.all { variant ->
- def name = variant.buildType.name
- def checkstyle = project.tasks.create "checkstyle${name.capitalize()}", Checkstyle
- checkstyle.dependsOn variant.javaCompile
- checkstyle.source variant.javaCompile.source
- checkstyle.classpath = project.fileTree(variant.javaCompile.destinationDir)
- checkstyle.exclude('**/BuildConfig.java')
- checkstyle.exclude('**/R.java')
- project.tasks.getByName("check").dependsOn checkstyle
-}
-
+apply from: 'gradle-make.gradle'
+apply from: 'gradle-config.gradle'
+apply from: 'gradle-device-farm.gradle'
apply from: 'gradle-spoon.gradle'
+apply from: 'gradle-checkstyle.gradle'
+
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/gradle-checkstyle.gradle b/platform/android/MapboxGLAndroidSDKTestApp/gradle-checkstyle.gradle
new file mode 100644
index 0000000000..cdcc7f1e23
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/gradle-checkstyle.gradle
@@ -0,0 +1,17 @@
+apply plugin: 'checkstyle'
+
+checkstyle {
+ toolVersion = "7.1.1" // 7.3
+ configFile = "../checkstyle.xml" as File
+}
+
+task checkstyle(type: Checkstyle) {
+ description 'Checks if the code adheres to coding standards'
+ group 'verification'
+ configFile file("../checkstyle.xml")
+ source 'src'
+ include '**/*.java'
+ exclude '**/gen/**'
+ classpath = files()
+ ignoreFailures = false
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/gradle-config.gradle b/platform/android/MapboxGLAndroidSDKTestApp/gradle-config.gradle
new file mode 100644
index 0000000000..21da83c4a0
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/gradle-config.gradle
@@ -0,0 +1,22 @@
+//
+// Configuration file for gradle build execution.
+//
+
+task accessToken {
+ def tokenFile = new File("MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml")
+ if (!tokenFile.exists()) {
+ String tokenFileContents = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<resources>\n" +
+ " <string name=\"mapbox_access_token\">" + "$System.env.MAPBOX_ACCESS_TOKEN" + "</string>\n" +
+ "</resources>"
+
+ if (tokenFileContents == null) {
+ throw new InvalidUserDataException("You must set the MAPBOX_ACCESS_TOKEN environment variable.")
+ }
+ tokenFile.write(tokenFileContents)
+ }
+}
+
+gradle.projectsEvaluated {
+ preBuild.dependsOn('accessToken')
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/gradle-device-farm.gradle b/platform/android/MapboxGLAndroidSDKTestApp/gradle-device-farm.gradle
new file mode 100644
index 0000000000..f455e263c0
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/gradle-device-farm.gradle
@@ -0,0 +1,43 @@
+apply plugin: 'devicefarm'
+
+def getAccessKeyDeviceFarm() {
+ if (project.hasProperty('AWS_ACCESS_KEY_ID_DEVICE_FARM')) {
+ return AWS_ACCESS_KEY_ID_DEVICE_FARM
+ } else {
+ println("Could not locate AWS_ACCESS_KEY_ID_DEVICE_FARM in gradle.properties")
+ return ""
+ }
+}
+
+def getSecretAccessKeyDeviceFarm() {
+ if (project.hasProperty('AWS_SECRET_ACCESS_KEY_DEVICE_FARM')) {
+ return AWS_SECRET_ACCESS_KEY_DEVICE_FARM
+ } else {
+ println("Could not locate AWS_SECRET_ACCESS_KEY_DEVICE_FARM in gradle.properties")
+ return ""
+ }
+}
+
+devicefarm {
+
+ projectName "Mapbox GL Android" // required: Must already exists.
+ devicePool "sanity" // optional: Defaults to "Top Devices"
+
+ authentication {
+ accessKey getAccessKeyDeviceFarm()
+ secretKey getSecretAccessKeyDeviceFarm()
+ }
+
+ devicestate {
+ wifi "on"
+ bluetooth "off"
+ gps "on"
+ nfc "on"
+ latitude 47.6204 // default
+ longitude - 122.3491 // default
+ }
+
+ instrumentation {
+
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/gradle-make.gradle b/platform/android/MapboxGLAndroidSDKTestApp/gradle-make.gradle
new file mode 100644
index 0000000000..29567df6f0
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/gradle-make.gradle
@@ -0,0 +1,18 @@
+//
+// Contains GL-native make commands
+//
+
+task makeClean(type: Exec) {
+ workingDir '../../'
+ commandLine 'make', 'clean'
+}
+
+task makeAndroid(type: Exec) {
+ workingDir '../../'
+ commandLine 'make', 'android'
+}
+
+task makeAndroidAll(type: Exec) {
+ workingDir '../../'
+ commandLine 'make', 'apackage'
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/lint.xml b/platform/android/MapboxGLAndroidSDKTestApp/lint.xml
deleted file mode 100644
index 94058fd4df..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/lint.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lint>
- <!-- Ignore errors caused by icon burning -->
- <issue id="IconLauncherShape" severity="ignore">
- <ignore path="res/drawable-mdpi/icon.png" />
- <ignore path="res/drawable-hdpi/icon.png" />
- <ignore path="res/drawable-xdpi/icon.png" />
- <ignore path="res/drawable-xxdpi/icon.png" />
- <ignore path="res/drawable-mdpi/icon_burned.png" />
- <ignore path="res/drawable-hdpi/icon_burned.png" />
- <ignore path="res/drawable-xdpi/icon_burned.png" />
- <ignore path="res/drawable-xxdpi/icon_burned.png" />
- </issue>
- <issue id="IconDuplicates" severity="ignore">
- <ignore path="res/drawable-mdpi/icon.png" />
- <ignore path="res/drawable-hdpi/icon.png" />
- <ignore path="res/drawable-xdpi/icon.png" />
- <ignore path="res/drawable-xxdpi/icon.png" />
- <ignore path="res/drawable-mdpi/icon_burned.png" />
- <ignore path="res/drawable-hdpi/icon_burned.png" />
- <ignore path="res/drawable-xdpi/icon_burned.png" />
- <ignore path="res/drawable-xxdpi/icon_burned.png" />
- </issue>
- <issue id="UnusedResources" severity="ignore">
- <ignore path="res/drawable-mdpi/icon.png" />
- <ignore path="res/drawable-hdpi/icon.png" />
- <ignore path="res/drawable-xdpi/icon.png" />
- <ignore path="res/drawable-xxdpi/icon.png" />
- <ignore path="res/drawable-mdpi/icon_burned.png" />
- <ignore path="res/drawable-hdpi/icon_burned.png" />
- <ignore path="res/drawable-xdpi/icon_burned.png" />
- <ignore path="res/drawable-xxdpi/icon_burned.png" />
- </issue>
-</lint>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro b/platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro
index 49c6038041..5d944b5dd4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro
+++ b/platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro
@@ -4,3 +4,5 @@
-dontwarn org.codehaus.**
-keep class com.google.**
-dontwarn com.google.**
+
+-keep class com.mapbox.mapboxsdk.testapp.model.customlayer.ExampleCustomLayer { *; }
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapViewUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapViewUtils.java
new file mode 100644
index 0000000000..38d5297291
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapViewUtils.java
@@ -0,0 +1,33 @@
+package com.mapbox.mapboxsdk.maps;
+
+import com.mapbox.mapboxsdk.geometry.LatLng;
+
+/**
+ * Utility class to bypass package visibility
+ */
+public class MapViewUtils {
+
+ public static void setDirection(MapboxMap mapboxMap, float direction) {
+ mapboxMap.getTransform().setBearing(direction);
+ }
+
+ public static float getDirection(MapboxMap mapboxMap) {
+ return (float) mapboxMap.getTransform().getBearing();
+ }
+
+ public static void setTilt(MapboxMap mapboxMap, float tilt) {
+ mapboxMap.getTransform().setTilt((double) tilt);
+ }
+
+ public static float getTilt(MapboxMap mapboxMap) {
+ return (float) mapboxMap.getTransform().getTilt();
+ }
+
+ public static void setLatLng(MapboxMap mapboxMap, LatLng latLng) {
+ mapboxMap.getTransform().setCenterCoordinate(latLng);
+ }
+
+ public static LatLng getLatLng(MapboxMap mapboxMap) {
+ return mapboxMap.getTransform().getCenterCoordinate();
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
new file mode 100644
index 0000000000..330de1e9c8
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
@@ -0,0 +1,826 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.graphics.Color;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerOptions;
+import com.mapbox.mapboxsdk.annotations.Polygon;
+import com.mapbox.mapboxsdk.annotations.PolygonOptions;
+import com.mapbox.mapboxsdk.annotations.Polyline;
+import com.mapbox.mapboxsdk.annotations.PolylineOptions;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.exceptions.InvalidMarkerPositionException;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import timber.log.Timber;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * This test is responsible for testing the public API.
+ * <p>
+ * Methods executed on MapboxMap are called from a ViewAction to ensure correct synchronisation
+ * with the application UI-thread.
+ * </p>
+ */
+public class MapboxMapTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+ private EspressoTestActivity activity;
+
+ @Before
+ public void beforeTest() {
+ activity = rule.getActivity();
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ idlingResource = new OnMapReadyIdlingResource(activity);
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testSanity() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ MapboxMap mapboxMap = activity.getMapboxMap();
+ assertNotNull("mapboxMap should not be null", mapboxMap);
+ }
+
+ //
+ // MinZoomLevel
+ //
+
+ @Test
+ public void testMinZoom() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ mapboxMap.setMinZoomPreference(10);
+ assertEquals("MinZoom should match", 10, mapboxMap.getMinZoomLevel(), 10);
+ }
+ }));
+ }
+
+ @Test
+ public void testMaxZoom() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ final double zoom = 10;
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ mapboxMap.setMaxZoomPreference(zoom);
+ assertEquals("MaxZoom should match", zoom, mapboxMap.getMaxZoomLevel(), 10);
+ }
+ }));
+ }
+
+ @Test
+ public void testInitialZoomLevels() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ assertEquals("MaxZoom should match", MapboxConstants.MAXIMUM_ZOOM, mapboxMap.getMaxZoomLevel(),
+ TestConstants.ZOOM_DELTA);
+ assertEquals("MinZoom should match", MapboxConstants.MINIMUM_ZOOM, mapboxMap.getMinZoomLevel(),
+ TestConstants.ZOOM_DELTA);
+ }
+ }));
+ }
+
+ //
+ // TrackingSettings
+ //
+
+ @Test
+ public void testTrackingSettings() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ MapboxMap mapboxMap = activity.getMapboxMap();
+ assertNotNull("TrackingSettings should not be null", mapboxMap.getTrackingSettings());
+ }
+
+ //
+ // InfoWindow
+ //
+
+ @Test
+ public void testConcurrentInfoWindowEnabled() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(true);
+ assertTrue("ConcurrentWindows should be true", mapboxMap.isAllowConcurrentMultipleOpenInfoWindows());
+ }
+ }));
+ }
+
+ @Test
+ public void testConcurrentInfoWindowDisabled() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(false);
+ assertFalse("ConcurrentWindows should be false", mapboxMap.isAllowConcurrentMultipleOpenInfoWindows());
+ }
+ }));
+ }
+
+ @Test
+ public void testInfoWindowAdapter() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MapboxMap.InfoWindowAdapter infoWindowAdapter = new MapboxMap.InfoWindowAdapter() {
+ @Nullable
+ @Override
+ public View getInfoWindow(@NonNull Marker marker) {
+ return null;
+ }
+ };
+ mapboxMap.setInfoWindowAdapter(infoWindowAdapter);
+ assertEquals("InfoWindowAdpter should be the same", infoWindowAdapter, mapboxMap.getInfoWindowAdapter());
+ }
+ }));
+ }
+
+ //
+ // Location
+ //
+
+ @Test
+ @Ignore /* disabled due to enabling permissions during test #7177 */
+ public void testMyLocationEnabled() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ mapboxMap.setMyLocationEnabled(true);
+ assertTrue("MyLocationEnabled should be true", mapboxMap.isMyLocationEnabled());
+ }
+ }));
+ }
+
+ @Test
+ @Ignore /* can't create handler inside thread that not called Looper.prepare() */
+ public void testMyLocationDisabled() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ mapboxMap.setMyLocationEnabled(false);
+ assertFalse("MyLocationEnabled should be false", mapboxMap.isMyLocationEnabled());
+ }
+ }));
+ }
+
+ //
+ // setters/getters interfaces
+ //
+
+ @Test
+ public void testFpsListener() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MapboxMap.OnFpsChangedListener fpsChangedListener = new MapboxMap.OnFpsChangedListener() {
+ @Override
+ public void onFpsChanged(double fps) {
+
+ }
+ };
+ mapboxMap.setOnFpsChangedListener(fpsChangedListener);
+ assertEquals("FpsListener should match", fpsChangedListener, mapboxMap.getOnFpsChangedListener());
+ }
+ }));
+ }
+
+ @Test
+ public void testInfoWindowClickListener() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MapboxMap.OnInfoWindowClickListener clickListener = new MapboxMap.OnInfoWindowClickListener() {
+ @Override
+ public boolean onInfoWindowClick(@NonNull Marker marker) {
+ return false;
+ }
+ };
+ mapboxMap.setOnInfoWindowClickListener(clickListener);
+ assertEquals("InfoWidowClickListener should match", clickListener, mapboxMap.getOnInfoWindowClickListener());
+ }
+ }));
+ }
+
+ @Test
+ public void testInfoWindowCloseListener() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MapboxMap.OnInfoWindowCloseListener listener = new MapboxMap.OnInfoWindowCloseListener() {
+ @Override
+ public void onInfoWindowClose(Marker marker) {
+
+ }
+ };
+ mapboxMap.setOnInfoWindowCloseListener(listener);
+ assertEquals("InfoWindowCloseListener should match", listener, mapboxMap.getOnInfoWindowCloseListener());
+ }
+ }));
+ }
+
+ @Test
+ public void testInfoWindowLongClickListener() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MapboxMap.OnInfoWindowLongClickListener listener = new MapboxMap.OnInfoWindowLongClickListener() {
+ @Override
+ public void onInfoWindowLongClick(Marker marker) {
+
+ }
+ };
+ mapboxMap.setOnInfoWindowLongClickListener(listener);
+ assertEquals("InfoWindowLongClickListener should match", listener,
+ mapboxMap.getOnInfoWindowLongClickListener());
+ }
+ }));
+ }
+
+ //
+ // Annotations
+ //
+
+ @Test
+ public void testAddMarker() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ assertTrue("Marker should be contained", mapboxMap.getMarkers().contains(marker));
+ }
+ }));
+ }
+
+ @Test(expected = InvalidMarkerPositionException.class)
+ public void testAddMarkerInvalidPosition() {
+ new MarkerOptions().getMarker();
+ }
+
+ @Test
+ public void testAddMarkers() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().position(new LatLng()).title("a");
+ MarkerOptions markerOptions2 = new MarkerOptions().position(new LatLng()).title("b");
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ List<Marker> markers = mapboxMap.addMarkers(markerList);
+ assertEquals("Markers size should be 2", 2, mapboxMap.getMarkers().size());
+ assertTrue(mapboxMap.getMarkers().contains(markers.get(0)));
+ assertTrue(mapboxMap.getMarkers().contains(markers.get(1)));
+ }
+ }));
+ }
+
+ @Test
+ public void testAddMarkersEmpty() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ mapboxMap.addMarkers(markerList);
+ assertEquals("Markers size should be 0", 0, mapboxMap.getMarkers().size());
+ }
+ }));
+ }
+
+ @Test
+ public void testAddMarkersSingleMarker() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions = new MarkerOptions().title("a").position(new LatLng());
+ markerList.add(markerOptions);
+ List<Marker> markers = mapboxMap.addMarkers(markerList);
+ assertEquals("Markers size should be 1", 1, mapboxMap.getMarkers().size());
+ assertTrue(mapboxMap.getMarkers().contains(markers.get(0)));
+ }
+ }));
+ }
+
+ @Test
+ public void testAddPolygon() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ PolygonOptions polygonOptions = new PolygonOptions().add(new LatLng());
+ Polygon polygon = mapboxMap.addPolygon(polygonOptions);
+ assertTrue("Polygon should be contained", mapboxMap.getPolygons().contains(polygon));
+ }
+ }));
+ }
+
+ @Test
+ public void testAddEmptyPolygon() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ PolygonOptions polygonOptions = new PolygonOptions();
+ Polygon polygon = mapboxMap.addPolygon(polygonOptions);
+ assertTrue("Polygon should be ignored", !mapboxMap.getPolygons().contains(polygon));
+ }
+ }));
+ }
+
+ @Test
+ public void testAddPolygons() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ List<PolygonOptions> polygonList = new ArrayList<>();
+ PolygonOptions polygonOptions1 = new PolygonOptions().fillColor(Color.BLACK).add(new LatLng());
+ PolygonOptions polygonOptions2 = new PolygonOptions().fillColor(Color.WHITE).add(new LatLng());
+ PolygonOptions polygonOptions3 = new PolygonOptions();
+ polygonList.add(polygonOptions1);
+ polygonList.add(polygonOptions2);
+ polygonList.add(polygonOptions3);
+ mapboxMap.addPolygons(polygonList);
+ assertEquals("Polygons size should be 2", 2, mapboxMap.getPolygons().size());
+ assertTrue(mapboxMap.getPolygons().contains(polygonOptions1.getPolygon()));
+ assertTrue(mapboxMap.getPolygons().contains(polygonOptions2.getPolygon()));
+ assertTrue("Polygon should be ignored", !mapboxMap.getPolygons().contains(polygonOptions3.getPolygon()));
+ }
+ }));
+ }
+
+ @Test
+ public void addPolygonsEmpty() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ mapboxMap.addPolygons(new ArrayList<PolygonOptions>());
+ assertEquals("Polygons size should be 0", 0, mapboxMap.getPolygons().size());
+ }
+ }));
+ }
+
+ @Test
+ public void addPolygonsSingle() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ List<PolygonOptions> polygonList = new ArrayList<>();
+ PolygonOptions polygonOptions = new PolygonOptions().fillColor(Color.BLACK).add(new LatLng());
+ polygonList.add(polygonOptions);
+ mapboxMap.addPolygons(polygonList);
+ assertEquals("Polygons size should be 1", 1, mapboxMap.getPolygons().size());
+ assertTrue(mapboxMap.getPolygons().contains(polygonOptions.getPolygon()));
+ }
+ }));
+ }
+
+ @Test
+ public void testAddPolyline() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ PolylineOptions polylineOptions = new PolylineOptions().add(new LatLng());
+ Polyline polyline = mapboxMap.addPolyline(polylineOptions);
+ assertTrue("Polyline should be contained", mapboxMap.getPolylines().contains(polyline));
+ }
+ }));
+ }
+
+ @Test
+ public void testAddEmptyPolyline() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ PolylineOptions polylineOptions = new PolylineOptions();
+ Polyline polyline = mapboxMap.addPolyline(polylineOptions);
+ assertTrue("Polyline should be ignored", !mapboxMap.getPolylines().contains(polyline));
+ }
+ }));
+ }
+
+ @Test
+ public void testAddPolylines() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ List<PolylineOptions> polylineList = new ArrayList<>();
+ PolylineOptions polygonOptions1 = new PolylineOptions().color(Color.BLACK).add(new LatLng());
+ PolylineOptions polygonOptions2 = new PolylineOptions().color(Color.WHITE).add(new LatLng());
+ PolylineOptions polygonOptions3 = new PolylineOptions();
+ polylineList.add(polygonOptions1);
+ polylineList.add(polygonOptions2);
+ polylineList.add(polygonOptions3);
+ mapboxMap.addPolylines(polylineList);
+ assertEquals("Polygons size should be 2", 2, mapboxMap.getPolylines().size());
+ assertTrue(mapboxMap.getPolylines().contains(polygonOptions1.getPolyline()));
+ assertTrue(mapboxMap.getPolylines().contains(polygonOptions2.getPolyline()));
+ assertTrue("Polyline should be ignored", !mapboxMap.getPolylines().contains(polygonOptions3.getPolyline()));
+ }
+ }));
+ }
+
+ @Test
+ public void testAddPolylinesEmpty() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ mapboxMap.addPolylines(new ArrayList<PolylineOptions>());
+ assertEquals("Polygons size should be 0", 0, mapboxMap.getPolylines().size());
+ }
+ }));
+ }
+
+ @Test
+ public void testAddPolylinesSingle() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ List<PolylineOptions> polylineList = new ArrayList<>();
+ PolylineOptions polygonOptions = new PolylineOptions().color(Color.BLACK).add(new LatLng());
+ polylineList.add(polygonOptions);
+ mapboxMap.addPolylines(polylineList);
+ assertEquals("Polygons size should be 1", 1, mapboxMap.getPolylines().size());
+ assertTrue(mapboxMap.getPolylines().contains(polygonOptions.getPolyline()));
+ }
+ }));
+ }
+
+ @Test
+ public void testRemoveMarker() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ mapboxMap.removeMarker(marker);
+ assertTrue("Markers should be empty", mapboxMap.getMarkers().isEmpty());
+ }
+ }));
+ }
+
+ @Test
+ public void testRemovePolygon() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ PolygonOptions polygonOptions = new PolygonOptions();
+ Polygon polygon = mapboxMap.addPolygon(polygonOptions);
+ mapboxMap.removePolygon(polygon);
+ assertTrue("Polygons should be empty", mapboxMap.getPolylines().isEmpty());
+ }
+ }));
+ }
+
+ @Test
+ public void testRemovePolyline() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ PolylineOptions polylineOptions = new PolylineOptions();
+ Polyline polyline = mapboxMap.addPolyline(polylineOptions);
+ mapboxMap.removePolyline(polyline);
+ assertTrue("Polylines should be empty", mapboxMap.getPolylines().isEmpty());
+ }
+ }));
+ }
+
+ @Test
+ public void testRemoveAnnotation() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ mapboxMap.removeAnnotation(marker);
+ assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
+ }
+ }));
+ }
+
+ @Test
+ public void testRemoveAnnotationById() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ mapboxMap.addMarker(markerOptions);
+ // id will always be 0 in unit tests
+ mapboxMap.removeAnnotation(0);
+ assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
+ }
+ }));
+ }
+
+ @Test
+ public void testRemoveAnnotations() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
+ MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ mapboxMap.addMarkers(markerList);
+ mapboxMap.removeAnnotations();
+ assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
+ }
+ }));
+ }
+
+ @Test
+ public void testClear() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
+ MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ mapboxMap.addMarkers(markerList);
+ mapboxMap.clear();
+ assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
+ }
+ }));
+ }
+
+ @Test
+ public void testRemoveAnnotationsByList() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
+ MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ List<Marker> markers = mapboxMap.addMarkers(markerList);
+ Marker marker = mapboxMap.addMarker(new MarkerOptions().position(new LatLng()).title("c"));
+ mapboxMap.removeAnnotations(markers);
+ assertTrue("Annotations should not be empty", mapboxMap.getAnnotations().size() == 1);
+ assertTrue("Marker should be contained", mapboxMap.getAnnotations().contains(marker));
+ }
+ }));
+ }
+
+ @Test
+ public void testGetAnnotationById() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker initialMarker = mapboxMap.addMarker(markerOptions);
+ Marker retrievedMarker = (Marker) mapboxMap.getAnnotation(0);
+ assertEquals("Markers should match", initialMarker, retrievedMarker);
+ }
+ }));
+ }
+
+ @Test
+ public void testGetAnnotations() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ assertNotNull("Annotations should be non null", mapboxMap.getAnnotations());
+ }
+ }));
+ }
+
+ @Test
+ public void testGetMarkers() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ assertNotNull("Markers should be non null", mapboxMap.getMarkers());
+ }
+ }));
+ }
+
+ @Test
+ public void testGetPolygons() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ assertNotNull("Polygons should be non null", mapboxMap.getPolygons());
+ }
+ }));
+ }
+
+ @Test
+ public void testGetPolylines() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ assertNotNull("Polylines should be non null", mapboxMap.getPolylines());
+ }
+ }));
+ }
+
+ @Test
+ public void testGetSelectedMarkers() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ assertNotNull("Selected markers should be non null", mapboxMap.getSelectedMarkers());
+ }
+ }));
+ }
+
+ @Test
+ public void testSelectMarker() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ mapboxMap.selectMarker(marker);
+ assertTrue("Marker should be contained", mapboxMap.getSelectedMarkers().contains(marker));
+ }
+ }));
+ }
+
+ @Test
+ public void testDeselectMarker() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ mapboxMap.selectMarker(marker);
+ mapboxMap.deselectMarker(marker);
+ assertTrue("Selected markers should be empty", mapboxMap.getSelectedMarkers().isEmpty());
+ }
+ }));
+ }
+
+ @Test
+ public void testDeselectMarkers() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = activity.getMapboxMap();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker1 = mapboxMap.addMarker(markerOptions);
+ Marker marker2 = mapboxMap.addMarker(markerOptions);
+ mapboxMap.selectMarker(marker1);
+ mapboxMap.selectMarker(marker2);
+ mapboxMap.deselectMarkers();
+ assertTrue("Selected markers should be empty", mapboxMap.getSelectedMarkers().isEmpty());
+ }
+ }));
+ }
+
+ @After
+ public void afterTest() {
+ Timber.e("@After test: unregister idle resource");
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+ private class MapboxMapAction implements ViewAction {
+
+ private InvokeViewAction invokeViewAction;
+
+ MapboxMapAction(InvokeViewAction invokeViewAction) {
+ this.invokeViewAction = invokeViewAction;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ invokeViewAction.onViewAction(uiController, view);
+ }
+ }
+
+ interface InvokeViewAction {
+ void onViewAction(UiController uiController, View view);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapUtils.java
deleted file mode 100644
index a88e5aeda5..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapUtils.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.mapbox.mapboxsdk.maps;
-
-/**
- * Utility class to bypass package visibility
- */
-public class MapboxMapUtils {
-
- public static void setDirection(MapView mapView, float direction) {
- mapView.setBearing(direction);
- }
-
- public static void setTilt(MapView mapView, float tilt) {
- mapView.setTilt((double) tilt);
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java
index b00255a6c7..2f51140cd1 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java
@@ -4,9 +4,9 @@ import android.app.Activity;
import android.support.test.espresso.Espresso;
import android.support.test.espresso.IdlingResourceTimeoutException;
import android.support.test.rule.ActivityTestRule;
-import android.util.Log;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import timber.log.Timber;
+
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
@@ -23,49 +23,50 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId;
public abstract class BaseActivityTest {
- @Rule
- public ActivityTestRule<Activity> rule = new ActivityTestRule<>(getActivityClass());
- protected MapboxMap mapboxMap;
- protected OnMapReadyIdlingResource idlingResource;
+ @Rule
+ public ActivityTestRule<Activity> rule = new ActivityTestRule<>(getActivityClass());
+ protected MapboxMap mapboxMap;
+ protected OnMapReadyIdlingResource idlingResource;
- @Before
- public void beforeTest() {
- try {
- Log.e(MapboxConstants.TAG, "@Before test: register idle resource");
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- checkViewIsDisplayed(R.id.mapView);
- mapboxMap = idlingResource.getMapboxMap();
- } catch (IdlingResourceTimeoutException e) {
- Log.e(MapboxConstants.TAG, "Idling resource timed out. Couldn't not validate if map is ready.");
- throw new RuntimeException("Could not start test for " + getActivityClass().getSimpleName() + ".\n" +
- "The ViewHierarchy doesn't contain a view with resource id = R.id.mapView or \n" +
- "the Activity doesn't contain an instance variable with a name equal to mapboxMap.\n" +
- "You can resolve this issue be implementing the requirements above or\n add " + getActivityClass().getSimpleName() + " to the excludeActivities array in `generate-test-code.js`.\n");
- }
+ @Before
+ public void beforeTest() {
+ try {
+ Timber.e("@Before test: register idle resource");
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ checkViewIsDisplayed(R.id.mapView);
+ mapboxMap = idlingResource.getMapboxMap();
+ } catch (IdlingResourceTimeoutException idlingResourceTimeoutException) {
+ Timber.e("Idling resource timed out. Couldn't not validate if map is ready.");
+ throw new RuntimeException("Could not start test for " + getActivityClass().getSimpleName() + ".\n"
+ + "The ViewHierarchy doesn't contain a view with resource id = R.id.mapView or \n"
+ + "the Activity doesn't contain an instance variable with a name equal to mapboxMap.\n"
+ + "You can resolve this issue be implementing the requirements above or\n add "
+ + getActivityClass().getSimpleName() + " to the excludeActivities array in `generate-test-code.js`.\n");
}
+ }
- protected abstract Class getActivityClass();
+ protected abstract Class getActivityClass();
- protected void checkViewIsDisplayed(int id) {
- onView(withId(id))
- .check(matches(isDisplayed()));
- }
+ protected void checkViewIsDisplayed(int id) {
+ onView(withId(id))
+ .check(matches(isDisplayed()));
+ }
- protected void takeScreenshot(final String name) {
- final Activity activity = rule.getActivity();
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- ScreenshotUtil.take(activity, name);
- }
- });
- }
+ protected void takeScreenshot(final String name) {
+ final Activity activity = rule.getActivity();
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ ScreenshotUtil.take(activity, name);
+ }
+ });
+ }
- @After
- public void afterTest() {
- Log.e(MapboxConstants.TAG, "@After test: unregister idle resource");
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void afterTest() {
+ Timber.e("@After test: unregister idle resource");
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/AddRemoveMarkerActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/AddRemoveMarkerActivityTest.java
deleted file mode 100644
index 76ee101904..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/AddRemoveMarkerActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.annotation.AddRemoveMarkerActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for AddRemoveMarkerActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class AddRemoveMarkerActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return AddRemoveMarkerActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/BulkMarkerActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/BulkMarkerActivityTest.java
deleted file mode 100644
index 33bfb23b25..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/BulkMarkerActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.annotation.BulkMarkerActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for BulkMarkerActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class BulkMarkerActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return BulkMarkerActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/DynamicMarkerChangeActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/DynamicMarkerChangeActivityTest.java
deleted file mode 100644
index 040affafda..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/DynamicMarkerChangeActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.annotation.DynamicMarkerChangeActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for DynamicMarkerChangeActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class DynamicMarkerChangeActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return DynamicMarkerChangeActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewActivityTest.java
deleted file mode 100644
index 9a0b66d8bc..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.annotation.MarkerViewActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for MarkerViewActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class MarkerViewActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return MarkerViewActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewScaleActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewScaleActivityTest.java
deleted file mode 100644
index 373b2d3d10..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewScaleActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.annotation.MarkerViewScaleActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for MarkerViewScaleActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class MarkerViewScaleActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return MarkerViewScaleActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolygonActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolygonActivityTest.java
deleted file mode 100644
index 9569b7880b..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolygonActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for PolygonActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class PolygonActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return PolygonActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolylineActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolylineActivityTest.java
deleted file mode 100644
index 32f099cbc8..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolylineActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.annotation.PolylineActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for PolylineActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class PolylineActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return PolylineActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PressForMarkerActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PressForMarkerActivityTest.java
deleted file mode 100644
index 3475a47263..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PressForMarkerActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.annotation.PressForMarkerActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for PressForMarkerActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class PressForMarkerActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return PressForMarkerActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraAnimationTypeActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraAnimationTypeActivityTest.java
deleted file mode 100644
index a4ee61de4d..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraAnimationTypeActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.camera;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.camera.CameraAnimationTypeActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for CameraAnimationTypeActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class CameraAnimationTypeActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return CameraAnimationTypeActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraPositionActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraPositionActivityTest.java
deleted file mode 100644
index 784488668c..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraPositionActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.camera;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.camera.CameraPositionActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for CameraPositionActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class CameraPositionActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return CameraPositionActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/LatLngBoundsActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/LatLngBoundsActivityTest.java
deleted file mode 100644
index f0b061a1c5..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/LatLngBoundsActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.camera;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.camera.LatLngBoundsActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for LatLngBoundsActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class LatLngBoundsActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return LatLngBoundsActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ManualZoomActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ManualZoomActivityTest.java
deleted file mode 100644
index 2a50f5f820..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ManualZoomActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.camera;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.camera.ManualZoomActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for ManualZoomActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class ManualZoomActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return ManualZoomActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/MaxMinZoomActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/MaxMinZoomActivityTest.java
deleted file mode 100644
index cb63bb8838..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/MaxMinZoomActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.camera;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.camera.MaxMinZoomActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for MaxMinZoomActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class MaxMinZoomActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return MaxMinZoomActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ScrollByActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ScrollByActivityTest.java
deleted file mode 100644
index ce594efd1f..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ScrollByActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.camera;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.camera.ScrollByActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for ScrollByActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class ScrollByActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return ScrollByActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/customlayer/CustomLayerActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/customlayer/CustomLayerActivityTest.java
deleted file mode 100644
index 56c2eae817..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/customlayer/CustomLayerActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.customlayer;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.customlayer.CustomLayerActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for CustomLayerActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class CustomLayerActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return CustomLayerActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/directions/DirectionsActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/directions/DirectionsActivityTest.java
deleted file mode 100644
index 379c57e55a..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/directions/DirectionsActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.directions;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.directions.DirectionsActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for DirectionsActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class DirectionsActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return DirectionsActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesBoxCountActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesBoxCountActivityTest.java
deleted file mode 100644
index c4a71d8279..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesBoxCountActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.feature;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.feature.QueryRenderedFeaturesBoxCountActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for QueryRenderedFeaturesBoxCountActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class QueryRenderedFeaturesBoxCountActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return QueryRenderedFeaturesBoxCountActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesPropertiesActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesPropertiesActivityTest.java
deleted file mode 100644
index 8a474fb9bf..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesPropertiesActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.feature;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.feature.QueryRenderedFeaturesPropertiesActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for QueryRenderedFeaturesPropertiesActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class QueryRenderedFeaturesPropertiesActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return QueryRenderedFeaturesPropertiesActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/geocoding/GeocoderActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/geocoding/GeocoderActivityTest.java
deleted file mode 100644
index 05d1f29547..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/geocoding/GeocoderActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.geocoding;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.geocoding.GeocoderActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for GeocoderActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class GeocoderActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return GeocoderActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/imagegenerator/PrintActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/imagegenerator/PrintActivityTest.java
deleted file mode 100644
index c14cc413cf..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/imagegenerator/PrintActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.imagegenerator;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.imagegenerator.PrintActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for PrintActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class PrintActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return PrintActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/DynamicInfoWindowAdapterActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/DynamicInfoWindowAdapterActivityTest.java
deleted file mode 100644
index b7a8245795..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/DynamicInfoWindowAdapterActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.infowindow;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.infowindow.DynamicInfoWindowAdapterActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for DynamicInfoWindowAdapterActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class DynamicInfoWindowAdapterActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return DynamicInfoWindowAdapterActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowActivityTest.java
deleted file mode 100644
index 5ba4d56a03..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.infowindow;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.infowindow.InfoWindowActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for InfoWindowActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class InfoWindowActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return InfoWindowActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowAdapterActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowAdapterActivityTest.java
deleted file mode 100644
index 7071874435..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowAdapterActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.infowindow;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.infowindow.InfoWindowAdapterActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for InfoWindowAdapterActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class InfoWindowAdapterActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return InfoWindowAdapterActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/DebugModeActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/DebugModeActivityTest.java
deleted file mode 100644
index 5764d364e0..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/DebugModeActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.maplayout;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.maplayout.DebugModeActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for DebugModeActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class DebugModeActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return DebugModeActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/MapPaddingActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/MapPaddingActivityTest.java
deleted file mode 100644
index 3f94b11246..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/MapPaddingActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.maplayout;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.maplayout.MapPaddingActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for MapPaddingActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class MapPaddingActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return MapPaddingActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/SurfaceViewMediaControlActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/SurfaceViewMediaControlActivityTest.java
deleted file mode 100644
index a52a4b0edb..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/SurfaceViewMediaControlActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.maplayout;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.maplayout.SurfaceViewMediaControlActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for SurfaceViewMediaControlActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class SurfaceViewMediaControlActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return SurfaceViewMediaControlActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/VideoViewActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/VideoViewActivityTest.java
deleted file mode 100644
index fb9330f0f4..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/VideoViewActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.maplayout;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.maplayout.VideoViewActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for VideoViewActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class VideoViewActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return VideoViewActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/offline/OfflineActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/offline/OfflineActivityTest.java
deleted file mode 100644
index 00a953f37e..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/offline/OfflineActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.offline;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.offline.OfflineActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for OfflineActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class OfflineActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return OfflineActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CircleLayerActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CircleLayerActivityTest.java
deleted file mode 100644
index 5299f2e716..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CircleLayerActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.style;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.style.CircleLayerActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for CircleLayerActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class CircleLayerActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return CircleLayerActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CustomSpriteActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CustomSpriteActivityTest.java
deleted file mode 100644
index 5e482b2b38..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CustomSpriteActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.style;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.style.CustomSpriteActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for CustomSpriteActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class CustomSpriteActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return CustomSpriteActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleActivityTest.java
deleted file mode 100644
index 37d5f64e8c..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.style;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for RuntimeStyleActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class RuntimeStyleActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return RuntimeStyleActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleTimingTestActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleTimingTestActivityTest.java
deleted file mode 100644
index 7320b8527c..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleTimingTestActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.style;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTimingTestActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for RuntimeStyleTimingTestActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class RuntimeStyleTimingTestActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return RuntimeStyleTimingTestActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/StyleFileActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/StyleFileActivityTest.java
deleted file mode 100644
index 29116b85cb..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/StyleFileActivityTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.testapp.activity.gen.style;
-
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.style.StyleFileActivity;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Sanity test for StyleFileActivity
- */
-@RunWith(AndroidJUnit4.class)
-public class StyleFileActivityTest extends BaseActivityTest {
-
- @Test
- public void testSanity() {
- onView(withId(R.id.mapView)).check(matches(isDisplayed()));
- }
-
- @Override
- protected Class getActivityClass() {
- return StyleFileActivity.class;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java
new file mode 100644
index 0000000000..77025c8fa5
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java
@@ -0,0 +1,142 @@
+package com.mapbox.mapboxsdk.testapp.annotations;
+
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerOptions;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static org.junit.Assert.assertEquals;
+
+public class MarkerTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+ private Marker marker;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ @Ignore
+ public void addMarkerTest() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+ assertEquals("Markers should be empty", 0, mapboxMap.getMarkers().size());
+
+ MarkerOptions options = new MarkerOptions();
+ options.setPosition(new LatLng());
+ options.setSnippet(TestConstants.TEXT_MARKER_SNIPPET);
+ options.setTitle(TestConstants.TEXT_MARKER_TITLE);
+
+ onView(withId(R.id.mapView)).perform(new AddMarkerAction(mapboxMap, options));
+ assertEquals("Markers sze should be 1, ", 1, mapboxMap.getMarkers().size());
+ assertEquals("Marker id should be 0", 0, marker.getId());
+ assertEquals("Marker target should match", new LatLng(), marker.getPosition());
+ assertEquals("Marker snippet should match", TestConstants.TEXT_MARKER_SNIPPET, marker.getSnippet());
+ assertEquals("Marker target should match", TestConstants.TEXT_MARKER_TITLE, marker.getTitle());
+ mapboxMap.clear();
+ assertEquals("Markers should be empty", 0, mapboxMap.getMarkers().size());
+ }
+
+ @Test
+ @Ignore
+ public void showInfoWindowTest() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final MarkerOptions options = new MarkerOptions();
+ options.setPosition(new LatLng());
+ options.setSnippet(TestConstants.TEXT_MARKER_SNIPPET);
+ options.setTitle(TestConstants.TEXT_MARKER_TITLE);
+
+ onView(withId(R.id.mapView)).perform(new AddMarkerAction(mapboxMap, options));
+ onView(withId(R.id.mapView)).perform(new ShowInfoWindowAction(mapboxMap));
+ onView(withText(TestConstants.TEXT_MARKER_TITLE)).check(matches(isDisplayed()));
+ onView(withText(TestConstants.TEXT_MARKER_SNIPPET)).check(matches(isDisplayed()));
+ }
+
+ private class AddMarkerAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+ private MarkerOptions options;
+
+ AddMarkerAction(MapboxMap map, MarkerOptions markerOptions) {
+ mapboxMap = map;
+ options = markerOptions;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ marker = mapboxMap.addMarker(options);
+ }
+ }
+
+ private class ShowInfoWindowAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+
+ ShowInfoWindowAction(MapboxMap map) {
+ mapboxMap = map;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mapboxMap.selectMarker(marker);
+
+ }
+ }
+
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerViewTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerViewTest.java
new file mode 100644
index 0000000000..9351ed1c10
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerViewTest.java
@@ -0,0 +1,147 @@
+package com.mapbox.mapboxsdk.testapp.annotations;
+
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.MarkerViewActivity;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.model.annotations.TextMarkerViewOptions;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static org.junit.Assert.assertEquals;
+
+public class MarkerViewTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+ private Marker marker;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ @Ignore
+ public void addMarkerViewTest() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+ assertEquals("Markers should be empty", 0, mapboxMap.getMarkers().size());
+
+ TextMarkerViewOptions options = new TextMarkerViewOptions();
+ options.text(TestConstants.TEXT_MARKER_TEXT);
+ options.position(new LatLng());
+ options.snippet(TestConstants.TEXT_MARKER_SNIPPET);
+ options.title(TestConstants.TEXT_MARKER_TITLE);
+
+ onView(withId(R.id.mapView)).perform(new AddTextMarkerViewAction(mapboxMap, options));
+ assertEquals("Markers sze should be 1, ", 1, mapboxMap.getMarkers().size());
+ assertEquals("Marker id should be 0", 0, marker.getId());
+ assertEquals("Marker target should match", new LatLng(), marker.getPosition());
+ assertEquals("Marker snippet should match", TestConstants.TEXT_MARKER_SNIPPET, marker.getSnippet());
+ assertEquals("Marker target should match", TestConstants.TEXT_MARKER_TITLE, marker.getTitle());
+ onView(withText(TestConstants.TEXT_MARKER_TEXT)).check(matches(isDisplayed()));
+ }
+
+ @Test
+ @Ignore
+ public void showInfoWindowTest() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final TextMarkerViewOptions options = new TextMarkerViewOptions();
+ options.position(new LatLng());
+ options.text(TestConstants.TEXT_MARKER_TEXT);
+ options.snippet(TestConstants.TEXT_MARKER_SNIPPET);
+ options.title(TestConstants.TEXT_MARKER_TITLE);
+
+ onView(withId(R.id.mapView)).perform(new AddTextMarkerViewAction(mapboxMap, options));
+ onView(withText(TestConstants.TEXT_MARKER_TEXT)).check(matches(isDisplayed()));
+ onView(withId(R.id.mapView)).perform(new ShowInfoWindowAction(mapboxMap));
+ onView(withText(TestConstants.TEXT_MARKER_TITLE)).check(matches(isDisplayed()));
+ onView(withText(TestConstants.TEXT_MARKER_SNIPPET)).check(matches(isDisplayed()));
+ }
+
+ private class AddTextMarkerViewAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+ private TextMarkerViewOptions options;
+
+ AddTextMarkerViewAction(MapboxMap map, TextMarkerViewOptions markerOptions) {
+ mapboxMap = map;
+ options = markerOptions;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mapboxMap.getMarkerViewManager().addMarkerViewAdapter(
+ new MarkerViewActivity.TextAdapter(view.getContext(), mapboxMap));
+ marker = mapboxMap.addMarker(options);
+ uiController.loopMainThreadForAtLeast(250);
+ }
+ }
+
+ private class ShowInfoWindowAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+
+ ShowInfoWindowAction(MapboxMap map) {
+ mapboxMap = map;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mapboxMap.selectMarker(marker);
+ uiController.loopMainThreadForAtLeast(250);
+ }
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java
new file mode 100644
index 0000000000..24b9b3bf01
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java
@@ -0,0 +1,105 @@
+package com.mapbox.mapboxsdk.testapp.annotations;
+
+import android.graphics.Color;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.annotations.Polygon;
+import com.mapbox.mapboxsdk.annotations.PolygonOptions;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static org.junit.Assert.assertEquals;
+
+public class PolygonTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+ private Polygon polygon;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ @Ignore
+ /** native crash **/
+ public void addPolygonTest() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+ LatLng latLngOne = new LatLng();
+ LatLng latLngTwo = new LatLng(1, 0);
+ LatLng latLngThree = new LatLng(1, 1);
+
+ assertEquals("Polygons should be empty", 0, mapboxMap.getPolygons().size());
+
+ final PolygonOptions options = new PolygonOptions();
+ options.strokeColor(Color.BLUE);
+ options.fillColor(Color.RED);
+ options.add(latLngOne);
+ options.add(latLngTwo);
+ options.add(latLngThree);
+
+ onView(withId(R.id.mapView)).perform(new AddPolygonAction(mapboxMap, options));
+
+ assertEquals("Polygons should be 1", 1, mapboxMap.getPolygons().size());
+ assertEquals("Polygon id should be 0", 0, polygon.getId());
+ assertEquals("Polygon points size should match", 3, polygon.getPoints().size());
+ assertEquals("Polygon stroke color should match", Color.BLUE, polygon.getStrokeColor());
+ assertEquals("Polygon target should match", Color.RED, polygon.getFillColor());
+ mapboxMap.clear();
+ assertEquals("Polygons should be empty", 0, mapboxMap.getPolygons().size());
+ }
+
+ private class AddPolygonAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+ private PolygonOptions options;
+
+ AddPolygonAction(MapboxMap map, PolygonOptions polygonOptions) {
+ mapboxMap = map;
+ options = polygonOptions;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ polygon = mapboxMap.addPolygon(options);
+ }
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java
new file mode 100644
index 0000000000..607a4ad263
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java
@@ -0,0 +1,100 @@
+package com.mapbox.mapboxsdk.testapp.annotations;
+
+import android.graphics.Color;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.annotations.Polyline;
+import com.mapbox.mapboxsdk.annotations.PolylineOptions;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static org.junit.Assert.assertEquals;
+
+public class PolylineTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+ private Polyline polyline;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Ignore
+ @Test
+ public void addPolylineTest() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+ LatLng latLngOne = new LatLng();
+ LatLng latLngTwo = new LatLng(1, 0);
+
+ assertEquals("Polygons should be empty", 0, mapboxMap.getPolygons().size());
+
+ final PolylineOptions options = new PolylineOptions();
+ options.color(Color.BLUE);
+ options.add(latLngOne);
+ options.add(latLngTwo);
+
+ onView(withId(R.id.mapView)).perform(new AddPolyLineAction(mapboxMap, options));
+
+ assertEquals("Polylines should be 1", 1, mapboxMap.getPolylines().size());
+ assertEquals("Polyline id should be 0", 0, polyline.getId());
+ assertEquals("Polyline points size should match", 2, polyline.getPoints().size());
+ assertEquals("Polyline stroke color should match", Color.BLUE, polyline.getColor());
+ mapboxMap.clear();
+ assertEquals("Polyline should be empty", 0, mapboxMap.getPolylines().size());
+ }
+
+ private class AddPolyLineAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+ private PolylineOptions options;
+
+ AddPolyLineAction(MapboxMap map, PolylineOptions polylineOptions) {
+ mapboxMap = map;
+ options = polylineOptions;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ polyline = mapboxMap.addPolyline(options);
+ }
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraAnimateTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraAnimateTest.java
new file mode 100644
index 0000000000..5ead54eb7b
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraAnimateTest.java
@@ -0,0 +1,253 @@
+package com.mapbox.mapboxsdk.testapp.camera;
+
+import android.graphics.PointF;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdate;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.geometry.LatLngBounds;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static org.junit.Assert.assertEquals;
+
+public class CameraAnimateTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testAnimateToCameraPositionTarget() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO remove zoom #6474*/
+ float zoom = 1.0f;
+ LatLng moveTarget = new LatLng(1, 1);
+
+ CameraPosition initialPosition = new CameraPosition.Builder().target(
+ new LatLng()).zoom(zoom).bearing(0).tilt(0).build();
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Default camera position should match default", cameraPosition, initialPosition);
+
+ onView(withId(R.id.mapView)).perform(new AnimateCameraAction(mapboxMap, CameraUpdateFactory.newLatLng(moveTarget)));
+ cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ }
+
+ @Test
+ public void testAnimateToCameraPositionTargetZoom() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final float moveZoom = 15.5f;
+ final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
+
+ onView(withId(R.id.mapView)).perform(new AnimateCameraAction(mapboxMap,
+ CameraUpdateFactory.newLatLngZoom(moveTarget, moveZoom)));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
+ }
+
+ @Test
+ public void testAnimateToCameraPosition() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
+ final float moveZoom = 15.5f;
+ final float moveTilt = 45.5f;
+ final float moveBearing = 12.5f;
+
+ onView(withId(R.id.mapView)).perform(
+ new AnimateCameraAction(mapboxMap, CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .target(moveTarget)
+ .zoom(moveZoom)
+ .tilt(moveTilt)
+ .bearing(moveBearing)
+ .build()))
+ );
+
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.tilt, moveTilt, TestConstants.TILT_DELTA);
+ assertEquals("Moved bearing should match", cameraPosition.bearing, moveBearing, TestConstants.BEARING_DELTA);
+ }
+
+ @Test
+ public void testAnimateToBounds() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final LatLng centerBounds = new LatLng(1, 1);
+ LatLng cornerOne = new LatLng();
+ LatLng cornerTwo = new LatLng(2, 2);
+
+ final LatLngBounds.Builder builder = new LatLngBounds.Builder();
+ builder.include(cornerOne);
+ builder.include(cornerTwo);
+
+ onView(withId(R.id.mapView)).perform(new AnimateCameraAction(mapboxMap,
+ CameraUpdateFactory.newLatLngBounds(builder.build(), 0)));
+
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match center bounds",
+ cameraPosition.target.getLatitude(),
+ centerBounds.getLatitude(),
+ TestConstants.LAT_LNG_DELTA);
+
+ assertEquals("Moved camera position longitude should match center bounds",
+ cameraPosition.target.getLongitude(),
+ centerBounds.getLongitude(),
+ TestConstants.LAT_LNG_DELTA);
+ }
+
+ @Test
+ public void testAnimateToMoveBy() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final PointF centerPoint = mapboxMap.getProjection().toScreenLocation(mapboxMap.getCameraPosition().target);
+ final LatLng moveTarget = new LatLng(2, 2);
+ final PointF moveTargetPoint = mapboxMap.getProjection().toScreenLocation(moveTarget);
+
+ onView(withId(R.id.mapView)).perform(new AnimateCameraAction(mapboxMap, CameraUpdateFactory.scrollBy(
+ moveTargetPoint.x - centerPoint.x, moveTargetPoint.y - centerPoint.y)));
+
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA_LARGE);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA_LARGE);
+ }
+
+ @Test
+ public void testAnimateToZoomIn() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO fix zoom #6474*/
+ float zoom = 1.0f;
+
+ onView(withId(R.id.mapView)).perform(new AnimateCameraAction(mapboxMap, CameraUpdateFactory.zoomIn()));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + 1,
+ TestConstants.ZOOM_DELTA);
+ }
+
+ @Test
+ public void testAnimateToZoomOut() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO fix zoom #6474*/
+ float zoom = 10.0f;
+ onView(withId(R.id.mapView)).perform(new AnimateCameraAction(mapboxMap,
+ CameraUpdateFactory.newLatLngZoom(new LatLng(), zoom)));
+ onView(withId(R.id.mapView)).perform(new AnimateCameraAction(mapboxMap, CameraUpdateFactory.zoomOut()));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom - 1,
+ TestConstants.ZOOM_DELTA);
+ }
+
+ @Test
+ public void testAnimateToZoomBy() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO fix zoom #6474*/
+ float zoom = 1.0f;
+ final float zoomBy = 2.45f;
+
+ onView(withId(R.id.mapView)).perform(new AnimateCameraAction(mapboxMap, CameraUpdateFactory.zoomBy(zoomBy)));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + zoomBy,
+ TestConstants.ZOOM_DELTA);
+ }
+
+ @Test
+ public void testAnimateToZoomTo() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO fix zoom #6474*/
+ final float zoomTo = 2.45f;
+
+ onView(withId(R.id.mapView)).perform(new AnimateCameraAction(mapboxMap, CameraUpdateFactory.zoomTo(zoomTo)));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoomTo,
+ TestConstants.ZOOM_DELTA);
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+ private class AnimateCameraAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+ private CameraUpdate cameraUpdate;
+
+ AnimateCameraAction(MapboxMap map, CameraUpdate update) {
+ mapboxMap = map;
+ cameraUpdate = update;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mapboxMap.animateCamera(cameraUpdate);
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ }
+ }
+}
+
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraEaseTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraEaseTest.java
new file mode 100644
index 0000000000..22af72cebb
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraEaseTest.java
@@ -0,0 +1,252 @@
+package com.mapbox.mapboxsdk.testapp.camera;
+
+import android.graphics.PointF;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdate;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.geometry.LatLngBounds;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static org.junit.Assert.assertEquals;
+
+public class CameraEaseTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testEaseToCameraPositionTarget() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO remove zoom #6474*/
+ float zoom = 1.0f;
+ LatLng moveTarget = new LatLng(1, 1);
+
+ CameraPosition initialPosition = new CameraPosition.Builder().target(
+ new LatLng()).zoom(zoom).bearing(0).tilt(0).build();
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Default camera position should match default", cameraPosition, initialPosition);
+
+ onView(withId(R.id.mapView)).perform(new EaseCameraAction(mapboxMap, CameraUpdateFactory.newLatLng(moveTarget)));
+ cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ }
+
+ @Test
+ public void testEaseToCameraPositionTargetZoom() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final float moveZoom = 15.5f;
+ final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
+
+ onView(withId(R.id.mapView)).perform(new EaseCameraAction(mapboxMap,
+ CameraUpdateFactory.newLatLngZoom(moveTarget, moveZoom)));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
+ }
+
+ @Test
+ public void testEaseToCameraPosition() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
+ final float moveZoom = 15.5f;
+ final float moveTilt = 45.5f;
+ final float moveBearing = 12.5f;
+
+ onView(withId(R.id.mapView)).perform(
+ new EaseCameraAction(mapboxMap, CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .target(moveTarget)
+ .zoom(moveZoom)
+ .tilt(moveTilt)
+ .bearing(moveBearing)
+ .build()))
+ );
+
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.tilt, moveTilt, TestConstants.TILT_DELTA);
+ assertEquals("Moved bearing should match", cameraPosition.bearing, moveBearing, TestConstants.BEARING_DELTA);
+ }
+
+ @Test
+ public void testEaseToBounds() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final LatLng centerBounds = new LatLng(1, 1);
+ LatLng cornerOne = new LatLng();
+ LatLng cornerTwo = new LatLng(2, 2);
+
+ final LatLngBounds.Builder builder = new LatLngBounds.Builder();
+ builder.include(cornerOne);
+ builder.include(cornerTwo);
+
+ onView(withId(R.id.mapView)).perform(new EaseCameraAction(mapboxMap,
+ CameraUpdateFactory.newLatLngBounds(builder.build(), 0)));
+
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match center bounds",
+ cameraPosition.target.getLatitude(),
+ centerBounds.getLatitude(),
+ TestConstants.LAT_LNG_DELTA);
+
+ assertEquals("Moved camera position longitude should match center bounds",
+ cameraPosition.target.getLongitude(),
+ centerBounds.getLongitude(),
+ TestConstants.LAT_LNG_DELTA);
+ }
+
+ @Test
+ public void testEaseToMoveBy() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final PointF centerPoint = mapboxMap.getProjection().toScreenLocation(mapboxMap.getCameraPosition().target);
+ final LatLng moveTarget = new LatLng(2, 2);
+ final PointF moveTargetPoint = mapboxMap.getProjection().toScreenLocation(moveTarget);
+
+ onView(withId(R.id.mapView)).perform(new EaseCameraAction(mapboxMap, CameraUpdateFactory.scrollBy(
+ moveTargetPoint.x - centerPoint.x, moveTargetPoint.y - centerPoint.y)));
+
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA_LARGE);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA_LARGE);
+ }
+
+ @Test
+ public void testEaseToZoomIn() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO fix zoom #6474*/
+ float zoom = 1.0f;
+
+ onView(withId(R.id.mapView)).perform(new EaseCameraAction(mapboxMap, CameraUpdateFactory.zoomIn()));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + 1,
+ TestConstants.ZOOM_DELTA);
+ }
+
+ @Test
+ public void testEaseToZoomOut() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO fix zoom #6474*/
+ float zoom = 10.0f;
+ onView(withId(R.id.mapView)).perform(new EaseCameraAction(mapboxMap,
+ CameraUpdateFactory.newLatLngZoom(new LatLng(), zoom)));
+ onView(withId(R.id.mapView)).perform(new EaseCameraAction(mapboxMap, CameraUpdateFactory.zoomOut()));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", 9, cameraPosition.zoom, TestConstants.ZOOM_DELTA);
+ }
+
+ @Test
+ public void testEaseToZoomBy() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO fix zoom #6474*/
+ float zoom = 1.0f;
+ final float zoomBy = 2.45f;
+
+ onView(withId(R.id.mapView)).perform(new EaseCameraAction(mapboxMap, CameraUpdateFactory.zoomBy(zoomBy)));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + zoomBy,
+ TestConstants.ZOOM_DELTA);
+ }
+
+ @Test
+ public void testEaseToZoomTo() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO fix zoom #6474*/
+ final float zoomTo = 2.45f;
+
+ onView(withId(R.id.mapView)).perform(new EaseCameraAction(mapboxMap, CameraUpdateFactory.zoomTo(zoomTo)));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoomTo,
+ TestConstants.ZOOM_DELTA);
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+ private class EaseCameraAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+ private CameraUpdate cameraUpdate;
+
+ EaseCameraAction(MapboxMap map, CameraUpdate update) {
+ mapboxMap = map;
+ cameraUpdate = update;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mapboxMap.easeCamera(cameraUpdate);
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ }
+ }
+}
+
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraInternalApiTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraInternalApiTest.java
new file mode 100644
index 0000000000..3ca61f7e9d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraInternalApiTest.java
@@ -0,0 +1,169 @@
+package com.mapbox.mapboxsdk.testapp.camera;
+
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapViewUtils;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests camera transformations that aren't part of our public API
+ */
+public class CameraInternalApiTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testBearing() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ EspressoTestActivity activity = rule.getActivity();
+ MapboxMap mapboxMap = activity.getMapboxMap();
+
+ CameraPosition initialPosition = new
+ CameraPosition.Builder().target(new LatLng()).zoom(1).bearing(0).tilt(0).build();
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Default camera position should match default", cameraPosition, initialPosition);
+
+ onView(withId(R.id.mapView)).perform(new BearingAction(mapboxMap));
+ assertEquals("Bearing should match", 45.1f, MapViewUtils.getDirection(mapboxMap), TestConstants.BEARING_DELTA);
+ }
+
+ @Test
+ public void testTilt() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ EspressoTestActivity activity = rule.getActivity();
+ MapboxMap mapboxMap = activity.getMapboxMap();
+
+ CameraPosition initialPosition = new CameraPosition.Builder().target(
+ new LatLng()).zoom(1).bearing(0).tilt(0).build();
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Default camera position should match default", cameraPosition, initialPosition);
+
+ onView(withId(R.id.mapView)).perform(new TiltAction(mapboxMap));
+ assertEquals("Tilt should match", 40.0f, MapViewUtils.getTilt(mapboxMap), TestConstants.TILT_DELTA);
+ }
+
+ @Test
+ public void testLatLng() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ EspressoTestActivity activity = rule.getActivity();
+ MapboxMap mapboxMap = activity.getMapboxMap();
+
+ CameraPosition initialPosition = new CameraPosition.Builder().target(
+ new LatLng()).zoom(1).bearing(0).tilt(0).build();
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Default camera position should match default", cameraPosition, initialPosition);
+
+ onView(withId(R.id.mapView)).perform(new LatLngAction(mapboxMap));
+ LatLng centerCoordinate = MapViewUtils.getLatLng(mapboxMap);
+ assertEquals("Latitude should match", 1.1f, centerCoordinate.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Longitude should match", 2.2f, centerCoordinate.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+ private class BearingAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+
+ BearingAction(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ MapViewUtils.setDirection(mapboxMap, -45.1f);
+ }
+ }
+
+ private class TiltAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+
+ TiltAction(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ MapViewUtils.setTilt(mapboxMap, 40.0f);
+ }
+ }
+
+ private class LatLngAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+
+ LatLngAction(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ MapViewUtils.setLatLng(mapboxMap, new LatLng(1.1, 2.2));
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraMoveTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraMoveTest.java
new file mode 100644
index 0000000000..b3a7fe0d11
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraMoveTest.java
@@ -0,0 +1,252 @@
+package com.mapbox.mapboxsdk.testapp.camera;
+
+import android.graphics.PointF;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdate;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.geometry.LatLngBounds;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static org.junit.Assert.assertEquals;
+
+public class CameraMoveTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testMoveToCameraPositionTarget() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO remove zoom #6474*/
+ float zoom = 1.0f;
+ LatLng moveTarget = new LatLng(1, 1);
+
+ CameraPosition initialPosition = new CameraPosition.Builder().target(
+ new LatLng()).zoom(zoom).bearing(0).tilt(0).build();
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Default camera position should match default", cameraPosition, initialPosition);
+
+ onView(withId(R.id.mapView)).perform(new MoveCameraAction(mapboxMap, CameraUpdateFactory.newLatLng(moveTarget)));
+ cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ }
+
+ @Test
+ public void testMoveToCameraPositionTargetZoom() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final float moveZoom = 15.5f;
+ final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
+
+ onView(withId(R.id.mapView)).perform(new MoveCameraAction(mapboxMap,
+ CameraUpdateFactory.newLatLngZoom(moveTarget, moveZoom)));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
+ }
+
+ @Test
+ public void testMoveToCameraPosition() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
+ final float moveZoom = 15.5f;
+ final float moveTilt = 45.5f;
+ final float moveBearing = 12.5f;
+
+ onView(withId(R.id.mapView)).perform(
+ new MoveCameraAction(mapboxMap, CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .target(moveTarget)
+ .zoom(moveZoom)
+ .tilt(moveTilt)
+ .bearing(moveBearing)
+ .build()))
+ );
+
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.tilt, moveTilt, TestConstants.TILT_DELTA);
+ assertEquals("Moved bearing should match", cameraPosition.bearing, moveBearing, TestConstants.BEARING_DELTA);
+ }
+
+ @Test
+ public void testMoveToBounds() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final LatLng centerBounds = new LatLng(1, 1);
+ LatLng cornerOne = new LatLng();
+ LatLng cornerTwo = new LatLng(2, 2);
+
+ final LatLngBounds.Builder builder = new LatLngBounds.Builder();
+ builder.include(cornerOne);
+ builder.include(cornerTwo);
+
+ onView(withId(R.id.mapView)).perform(new MoveCameraAction(mapboxMap,
+ CameraUpdateFactory.newLatLngBounds(builder.build(), 0)));
+
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match center bounds",
+ cameraPosition.target.getLatitude(),
+ centerBounds.getLatitude(),
+ TestConstants.LAT_LNG_DELTA);
+
+ assertEquals("Moved camera position longitude should match center bounds",
+ cameraPosition.target.getLongitude(),
+ centerBounds.getLongitude(),
+ TestConstants.LAT_LNG_DELTA);
+ }
+
+ @Test
+ public void testMoveToMoveBy() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ final PointF centerPoint = mapboxMap.getProjection().toScreenLocation(mapboxMap.getCameraPosition().target);
+ final LatLng moveTarget = new LatLng(2, 2);
+ final PointF moveTargetPoint = mapboxMap.getProjection().toScreenLocation(moveTarget);
+
+ onView(withId(R.id.mapView)).perform(new MoveCameraAction(mapboxMap, CameraUpdateFactory.scrollBy(
+ moveTargetPoint.x - centerPoint.x, moveTargetPoint.y - centerPoint.y)));
+
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA_LARGE);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA_LARGE);
+ }
+
+ @Test
+ public void testMoveToZoomIn() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO fix zoom #6474*/
+ float zoom = 1.0f;
+
+ onView(withId(R.id.mapView)).perform(new MoveCameraAction(mapboxMap, CameraUpdateFactory.zoomIn()));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + 1,
+ TestConstants.ZOOM_DELTA);
+ }
+
+ @Test
+ public void testMoveToZoomOut() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO fix zoom #6474*/
+ float zoom = 10.0f;
+ onView(withId(R.id.mapView)).perform(new MoveCameraAction(mapboxMap,
+ CameraUpdateFactory.newLatLngZoom(new LatLng(), zoom)));
+ onView(withId(R.id.mapView)).perform(new MoveCameraAction(mapboxMap, CameraUpdateFactory.zoomOut()));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom - 1,
+ TestConstants.ZOOM_DELTA);
+ }
+
+ @Test
+ public void testMoveToZoomBy() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO fix zoom #6474*/
+ float zoom = 1.0f;
+ final float zoomBy = 2.45f;
+
+ onView(withId(R.id.mapView)).perform(new MoveCameraAction(mapboxMap, CameraUpdateFactory.zoomBy(zoomBy)));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + zoomBy,
+ TestConstants.ZOOM_DELTA);
+ }
+
+ @Test
+ public void testMoveToZoomTo() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ final MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ /*TODO fix zoom #6474*/
+ final float zoomTo = 2.45f;
+
+ onView(withId(R.id.mapView)).perform(new MoveCameraAction(mapboxMap, CameraUpdateFactory.zoomTo(zoomTo)));
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoomTo,
+ TestConstants.ZOOM_DELTA);
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+ private class MoveCameraAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+ private CameraUpdate cameraUpdate;
+
+ MoveCameraAction(MapboxMap map, CameraUpdate update) {
+ mapboxMap = map;
+ cameraUpdate = update;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mapboxMap.moveCamera(cameraUpdate);
+ uiController.loopMainThreadForAtLeast(100);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/RotateActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/RotateActivityTest.java
deleted file mode 100644
index edef97027e..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/RotateActivityTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.camera;
-
-import android.support.test.espresso.UiController;
-import android.support.test.espresso.ViewAction;
-import android.view.View;
-
-import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMapUtils;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.activity.infowindow.InfoWindowActivity;
-
-import org.hamcrest.Matcher;
-import org.junit.Test;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-public class RotateActivityTest extends BaseActivityTest {
-
- @Test
- // longer testing change second param
- public void testRotate() {
- onView(withId(R.id.mapView)).perform(new RotateAction(0, 1));
- }
-
- @Override
- public Class getActivityClass() {
- return InfoWindowActivity.class;
- }
-
- private class RotateAction implements ViewAction {
-
- private float startDegree;
- private float endDegree;
-
- public RotateAction(float startDegree, float endDegree) {
- this.startDegree = startDegree;
- this.endDegree = endDegree;
- }
-
- @Override
- public Matcher<View> getConstraints() {
- return isDisplayed();
- }
-
- @Override
- public String getDescription() {
- return "rotateAction";
- }
-
- @Override
- public void perform(UiController uiController, View view) {
- uiController.loopMainThreadForAtLeast(500);
- for (float i = startDegree; i < endDegree; i++) {
- MapboxMapUtils.setDirection((MapView) view, i);
- uiController.loopMainThreadForAtLeast(1);
- }
- }
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/TiltActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/TiltActivityTest.java
deleted file mode 100644
index 8f21f60fb0..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/TiltActivityTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.camera;
-
-import android.support.test.espresso.UiController;
-import android.support.test.espresso.ViewAction;
-import android.view.View;
-
-import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMapUtils;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.activity.annotation.DynamicMarkerChangeActivity;
-
-import org.hamcrest.Matcher;
-import org.junit.Test;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-public class TiltActivityTest extends BaseActivityTest {
-
- @Test
- // longer testing change param
- public void testTilt() {
- onView(withId(R.id.mapView)).perform(new TiltAction(0, 1));
- }
-
- @Override
- public Class getActivityClass() {
- return DynamicMarkerChangeActivity.class;
- }
-
- private class TiltAction implements ViewAction {
-
- private float startDegree;
- private float endDegree;
-
- public TiltAction(float startDegree, float endDegree) {
- this.startDegree = startDegree;
- this.endDegree = endDegree;
- }
-
- @Override
- public Matcher<View> getConstraints() {
- return isDisplayed();
- }
-
- @Override
- public String getDescription() {
- return "tiltAction";
- }
-
- @Override
- public void perform(UiController uiController, View view) {
- uiController.loopMainThreadForAtLeast(500);
- for (float i = startDegree; i < endDegree; i++) {
- MapboxMapUtils.setTilt((MapView) view, i);
- uiController.loopMainThreadForAtLeast(1);
- }
- }
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/ZoomActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/ZoomActivityTest.java
deleted file mode 100644
index 700e8f6c5c..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/ZoomActivityTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.camera;
-
-import android.support.test.espresso.UiController;
-import android.support.test.espresso.ViewAction;
-import android.view.View;
-
-import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.activity.maplayout.DebugModeActivity;
-
-import org.hamcrest.Matcher;
-import org.junit.Test;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-public class ZoomActivityTest extends BaseActivityTest {
-
- @Test
- // longer testing increase second param
- public void testZoom() throws Exception {
- onView(withId(R.id.mapView)).perform(new ZoomAction(MapboxConstants.MINIMUM_ZOOM, MapboxConstants.MINIMUM_ZOOM - 1));
- }
-
- @Override
- public Class getActivityClass() {
- return DebugModeActivity.class;
- }
-
- private class ZoomAction implements ViewAction {
-
- private float fromZoom;
- private float toZoom;
-
- public ZoomAction(float fromZoom, float toZoom) {
- this.fromZoom = fromZoom;
- this.toZoom = toZoom;
- }
-
- @Override
- public Matcher<View> getConstraints() {
- return isDisplayed();
- }
-
- @Override
- public String getDescription() {
- return "zoomAction";
- }
-
- @Override
- public void perform(UiController uiController, View view) {
- // move camera above denver
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
- new CameraPosition.Builder()
- .target(new LatLng(39.749750, -104.949559))
- .build()));
-
- uiController.loopMainThreadForAtLeast(500);
-
- for (float i = fromZoom; i < toZoom; i++) {
- mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(i));
- uiController.loopMainThreadForAtLeast(200);
- }
- }
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesBoxCountTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesBoxCountTest.java
new file mode 100644
index 0000000000..b4be73be7a
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesBoxCountTest.java
@@ -0,0 +1,61 @@
+package com.mapbox.mapboxsdk.testapp.feature;
+
+import android.support.test.espresso.Espresso;
+import android.support.test.rule.ActivityTestRule;
+
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.feature.QueryRenderedFeaturesBoxCountActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+
+/**
+ * Instrumentation test to validate if clicking on the blue rectangle from
+ * QueryRenderedFeaturesBoxSymbolCountActivity shows a Toast that 149 features were found.
+ */
+public class QueryRenderedFeaturesBoxCountTest {
+
+ @Rule
+ public final ActivityTestRule<QueryRenderedFeaturesBoxCountActivity> rule =
+ new ActivityTestRule<>(QueryRenderedFeaturesBoxCountActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ @Ignore
+ public void testCountFeatures() {
+ // click on box to query map
+ onView(withId(R.id.selection_box)).perform(click());
+
+ // validate if toast is shown
+ onView(withText("149 features in box"))
+ .inRoot(withDecorView(not(is(rule.getActivity().getWindow().getDecorView()))))
+ .check(matches(isDisplayed()));
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesHighlightTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesHighlightTest.java
new file mode 100644
index 0000000000..b8cd46e612
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesHighlightTest.java
@@ -0,0 +1,81 @@
+package com.mapbox.mapboxsdk.testapp.feature;
+
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.action.CoordinatesProvider;
+import android.support.test.espresso.action.GeneralClickAction;
+import android.support.test.espresso.action.Press;
+import android.support.test.espresso.action.Tap;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.feature.QueryRenderedFeaturesBoxHighlightActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+
+/**
+ * Instrumentation test to validate if clicking box on screen highlights features.
+ */
+public class QueryRenderedFeaturesHighlightTest {
+
+ @Rule
+ public final ActivityTestRule<QueryRenderedFeaturesBoxHighlightActivity> rule =
+ new ActivityTestRule<>(QueryRenderedFeaturesBoxHighlightActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ @Ignore
+ public void testCountFeatures() {
+ // click on box to query map
+ onView(withId(R.id.selection_box)).perform(click());
+
+ // validate if toast is shown
+ onView(withText("50 features in box"))
+ .inRoot(withDecorView(not(is(rule.getActivity().getWindow().getDecorView()))))
+ .check(matches(isDisplayed()));
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+ private static ViewAction clickXY(final float x, final float y) {
+ return new GeneralClickAction(
+ Tap.SINGLE,
+ new CoordinatesProvider() {
+ @Override
+ public float[] calculateCoordinates(View view) {
+ final int[] screenPos = new int[2];
+ view.getLocationOnScreen(screenPos);
+ final float screenX = screenPos[0] + x;
+ final float screenY = screenPos[1] + y;
+ return new float[] {screenX, screenY};
+ }
+ },
+ Press.FINGER);
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesPropertiesTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesPropertiesTest.java
new file mode 100644
index 0000000000..3b86397603
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesPropertiesTest.java
@@ -0,0 +1,78 @@
+package com.mapbox.mapboxsdk.testapp.feature;
+
+import android.graphics.PointF;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.action.CoordinatesProvider;
+import android.support.test.espresso.action.GeneralClickAction;
+import android.support.test.espresso.action.Press;
+import android.support.test.espresso.action.Tap;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.feature.QueryRenderedFeaturesPropertiesActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+/**
+ * Instrumentation test to validate if clicking center of screen returns the correct features.
+ */
+public class QueryRenderedFeaturesPropertiesTest {
+
+ @Rule
+ public final ActivityTestRule<QueryRenderedFeaturesPropertiesActivity> rule =
+ new ActivityTestRule<>(QueryRenderedFeaturesPropertiesActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ @Ignore
+ public void testCountFeatures() {
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+ LatLng centerScreen = mapboxMap.getCameraPosition().target;
+ PointF centerPixel = mapboxMap.getProjection().toScreenLocation(centerScreen);
+ onView(withId(R.id.mapView)).perform(clickXY(centerPixel.x, centerPixel.y));
+ onView(withText("Found 4 features")).check(matches(isDisplayed()));
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+ private static ViewAction clickXY(final float x, final float y) {
+ return new GeneralClickAction(
+ Tap.SINGLE,
+ new CoordinatesProvider() {
+ @Override
+ public float[] calculateCoordinates(View view) {
+ final int[] screenPos = new int[2];
+ view.getLocationOnScreen(screenPos);
+ final float screenX = screenPos[0] + x;
+ final float screenY = screenPos[1] + y;
+ return new float[] {screenX, screenY};
+ }
+ },
+ Press.FINGER);
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedSymbolBoxCountTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedSymbolBoxCountTest.java
new file mode 100644
index 0000000000..ea80e8689a
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedSymbolBoxCountTest.java
@@ -0,0 +1,62 @@
+package com.mapbox.mapboxsdk.testapp.feature;
+
+import android.support.test.espresso.Espresso;
+import android.support.test.rule.ActivityTestRule;
+
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.feature.QueryRenderedFeaturesBoxSymbolCountActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+
+/**
+ * Instrumentation test to validate if clicking on the blue rectangle from
+ * QueryRenderedFeaturesBoxSymbolCountActivity shows a Toast that 2 symbols were found.
+ */
+public class QueryRenderedSymbolBoxCountTest {
+
+ @Rule
+ public final ActivityTestRule<QueryRenderedFeaturesBoxSymbolCountActivity> rule =
+ new ActivityTestRule<>(QueryRenderedFeaturesBoxSymbolCountActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ @Ignore
+ public void testCountSymbols() {
+ // click on box to query map
+ onView(withId(R.id.selection_box)).perform(click());
+
+ // validate if toast is shown
+ onView(withText("2 features in box"))
+ .inRoot(withDecorView(not(is(rule.getActivity().getWindow().getDecorView()))))
+ .check(matches(isDisplayed()));
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+}
+
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java
new file mode 100644
index 0000000000..fa1451092a
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java
@@ -0,0 +1,156 @@
+package com.mapbox.mapboxsdk.testapp.maps.widgets;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.net.Uri;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.intent.Intents;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.intent.Intents.intended;
+import static android.support.test.espresso.intent.Intents.intending;
+import static android.support.test.espresso.intent.matcher.IntentMatchers.hasAction;
+import static android.support.test.espresso.intent.matcher.IntentMatchers.hasData;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.core.IsNot.not;
+
+public class AttributionTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ private String[] dialogTexts;
+ private String[] dialogLinks;
+
+ @Before
+ public void beforeTest() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ Intents.init();
+ dialogTexts = rule.getActivity().getResources().getStringArray(R.array.mapbox_attribution_names);
+ dialogLinks = rule.getActivity().getResources().getStringArray(R.array.mapbox_attribution_links);
+ }
+
+ @Test
+ public void testDisabled() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ // Default
+ onView(withId(R.id.attributionView)).check(matches(isDisplayed()));
+
+ // Disabled
+ onView(withId(R.id.attributionView))
+ .perform(new DisableAction(mapboxMap))
+ .check(matches(not(isDisplayed())));
+ }
+
+ @Test
+ public void testMapboxLink() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+
+ // click on View to open dialog
+ onView(withId(R.id.attributionView)).perform(click());
+ onView(withText(R.string.mapbox_attributionsDialogTitle)).check(matches(isDisplayed()));
+
+ // click on link and validate browser opening
+ Matcher<Intent> expectedIntent = allOf(hasAction(Intent.ACTION_VIEW), hasData(Uri.parse(dialogLinks[0])));
+ intending(expectedIntent).respondWith(new Instrumentation.ActivityResult(0, null));
+ onView(withText(dialogTexts[0])).perform(click());
+ intended(expectedIntent);
+ }
+
+ @Test
+ public void testOpenStreetMapLink() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+
+ // click on View to open dialog
+ onView(withId(R.id.attributionView)).perform(click());
+ onView(withText(R.string.mapbox_attributionsDialogTitle)).check(matches(isDisplayed()));
+
+ // click on link and validate browser opening
+ Matcher<Intent> expectedIntent = allOf(hasAction(Intent.ACTION_VIEW), hasData(Uri.parse(dialogLinks[1])));
+ intending(expectedIntent).respondWith(new Instrumentation.ActivityResult(0, null));
+ onView(withText(dialogTexts[1])).perform(click());
+ }
+
+ @Test
+ public void testImproveMapLink() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+
+ // click on View to open dialog
+ onView(withId(R.id.attributionView)).perform(click());
+ onView(withText(R.string.mapbox_attributionsDialogTitle)).check(matches(isDisplayed()));
+
+ // click on Mapbox link and validate browser opening
+ Matcher<Intent> expectedIntent = allOf(hasAction(Intent.ACTION_VIEW), hasData(Uri.parse(dialogLinks[3])));
+ intending(expectedIntent).respondWith(new Instrumentation.ActivityResult(0, null));
+ onView(withText(dialogTexts[3])).perform(click());
+ }
+
+ @Test
+ public void testTelemetryDialog() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+
+ // click on View to open dialog
+ onView(withId(R.id.attributionView)).perform(click());
+ onView(withText(R.string.mapbox_attributionsDialogTitle)).check(matches(isDisplayed()));
+
+ // click on item to open second dialog
+ onView(withText(dialogTexts[3])).perform(click());
+ onView(withText(R.string.mapbox_attributionTelemetryTitle)).check(matches(isDisplayed()));
+ }
+
+ @After
+ public void afterTest() {
+ Intents.release();
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+ private class DisableAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+
+ DisableAction(MapboxMap map) {
+ mapboxMap = map;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mapboxMap.getUiSettings().setAttributionEnabled(false);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java
new file mode 100644
index 0000000000..02fec41f65
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java
@@ -0,0 +1,153 @@
+package com.mapbox.mapboxsdk.testapp.maps.widgets;
+
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdate;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+
+public class CompassViewTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testDefault() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ onView(withId(R.id.compassView)).check(matches(not(isDisplayed())));
+ }
+
+ @Test
+ public void testVisible() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ onView(withId(R.id.mapView)).perform(new MoveCameraAction(mapboxMap,
+ CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .bearing(45)
+ .zoom(1)
+ .target(new LatLng())
+ .build()
+ )
+ )
+ );
+
+ onView(withId(R.id.compassView)).check(matches(isDisplayed()));
+ }
+
+ @Test
+ @Ignore // 10-31-2016 click action is not working
+ public void testClick() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ onView(withId(R.id.mapView)).perform(new MoveCameraAction(mapboxMap,
+ CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .bearing(45)
+ .zoom(1)
+ .target(new LatLng())
+ .build()
+ )
+ )
+ );
+
+ onView(withId(R.id.compassView)).perform(click());
+ onView(withId(R.id.mapView)).perform(new WaitAction(3000));
+ onView(withId(R.id.compassView)).check(matches(not(isDisplayed())));
+
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Camera bearing should face north, ", 0, cameraPosition.bearing, TestConstants.BEARING_DELTA);
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+ private class WaitAction implements ViewAction {
+
+ private long waitTime;
+
+ WaitAction(long waitTime) {
+ this.waitTime = waitTime;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ uiController.loopMainThreadForAtLeast(waitTime);
+ }
+ }
+
+ private class MoveCameraAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+ private CameraUpdate cameraUpdate;
+
+ MoveCameraAction(MapboxMap map, CameraUpdate update) {
+ mapboxMap = map;
+ cameraUpdate = update;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mapboxMap.moveCamera(cameraUpdate);
+ }
+ }
+}
+
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/LogoTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/LogoTest.java
new file mode 100644
index 0000000000..f12b2bf160
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/LogoTest.java
@@ -0,0 +1,84 @@
+package com.mapbox.mapboxsdk.testapp.maps.widgets;
+
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static org.hamcrest.Matchers.not;
+
+public class LogoTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testDefault() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ onView(withId(R.id.logoView)).check(matches(isDisplayed()));
+ }
+
+ @Test
+ public void testDisabled() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ onView(withId(R.id.logoView))
+ .perform(new DisableAction(mapboxMap))
+ .check(matches(not(isDisplayed())));
+ }
+
+ @After
+ public void unregisterIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+ private class DisableAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+
+ DisableAction(MapboxMap map) {
+ mapboxMap = map;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mapboxMap.getUiSettings().setLogoEnabled(false);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/MyLocationViewTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/MyLocationViewTest.java
new file mode 100644
index 0000000000..ac10d11922
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/MyLocationViewTest.java
@@ -0,0 +1,246 @@
+package com.mapbox.mapboxsdk.testapp.maps.widgets;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.constants.MyBearingTracking;
+import com.mapbox.mapboxsdk.constants.MyLocationTracking;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.location.LocationServices;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static org.hamcrest.Matchers.not;
+
+/**
+ * Experimental MyLocationView tests,
+ * requires application to be granted with runtime location permissions.
+ * <p>
+ * Tests for enabling and disabling the {@link MyLocationView}.
+ * Tests for enabling tracking modes and if the correct default images are shown when toggling
+ * {@link com.mapbox.mapboxsdk.maps.TrackingSettings#setMyLocationTrackingMode(int)} &
+ * {@link com.mapbox.mapboxsdk.maps.TrackingSettings#setMyBearingTrackingMode(int)}.
+ * </p>
+ */
+public class MyLocationViewTest {
+
+ @Rule
+ public final ActivityTestRule<EspressoTestActivity> rule = new ActivityTestRule<>(EspressoTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void beforeTest() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ @Ignore // requires runtime permissions, disabled for CI
+ public void testEnabled() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+ onView(withId(R.id.userLocationView)).check(matches(not(isDisplayed())));
+ onView(withId(R.id.mapView)).perform(new ToggleLocationAction(mapboxMap, true));
+ onView(withId(R.id.userLocationView)).check(matches(isDisplayed()));
+ onView(withId(R.id.mapView)).perform(new ToggleLocationAction(mapboxMap, false));
+ onView(withId(R.id.userLocationView)).check(matches(not(isDisplayed())));
+ }
+
+ @Test
+ @Ignore
+ // requires runtime permissions, disabled for CI + issue with android.support.test.espresso.AppNotIdleException:
+ // Looped for 5049 iterations over 60 SECONDS.
+ public void testTracking() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+ onView(withId(R.id.userLocationView)).check(matches(not(isDisplayed())));
+ onView(withId(R.id.mapView)).perform(new EnableLocationTrackingAction(mapboxMap));
+ onView(withId(R.id.userLocationView)).check(matches(isDisplayed()));
+ onView(withId(R.id.userLocationView)).check(matches(new DrawableMatcher(mapboxMap,
+ R.drawable.mapbox_mylocation_icon_default, false)));
+ onView(withId(R.id.mapView)).perform(new EnableCompassBearingTrackingAction(mapboxMap));
+ onView(withId(R.id.userLocationView)).check(matches(new DrawableMatcher(mapboxMap,
+ R.drawable.mapbox_mylocation_icon_bearing, true)));
+ }
+
+ @After
+ public void afterTest() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+ private class ToggleLocationAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+ private boolean isEnabled;
+
+ ToggleLocationAction(MapboxMap map, boolean enable) {
+ mapboxMap = map;
+ isEnabled = enable;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ if (isEnabled) {
+ // move camera above user location
+ mapboxMap.moveCamera(
+ CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .target(new LatLng(LocationServices.getLocationServices(view.getContext()).getLastLocation()))
+ .build()
+ )
+ );
+ }
+
+ // show loction on screen
+ mapboxMap.setMyLocationEnabled(isEnabled);
+ }
+ }
+
+ private class EnableLocationTrackingAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+
+ EnableLocationTrackingAction(MapboxMap map) {
+ mapboxMap = map;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mapboxMap.getTrackingSettings().setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
+ }
+ }
+
+ private class EnableCompassBearingTrackingAction implements ViewAction {
+
+ private MapboxMap mapboxMap;
+
+ EnableCompassBearingTrackingAction(MapboxMap map) {
+ mapboxMap = map;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mapboxMap.getTrackingSettings().setMyBearingTrackingMode(MyBearingTracking.COMPASS);
+ // wait for next compass update cycle
+ uiController.loopMainThreadForAtLeast(500);
+ }
+ }
+
+ private class DrawableMatcher extends TypeSafeMatcher<View> {
+
+ private MapboxMap mapboxMap;
+ private boolean isBearingDrawable;
+ private final int expectedId;
+
+ DrawableMatcher(MapboxMap mapboxMap, int expectedId, boolean isBearingDrawable) {
+ super(MyLocationView.class);
+ this.mapboxMap = mapboxMap;
+ this.expectedId = expectedId;
+ this.isBearingDrawable = isBearingDrawable;
+ }
+
+ @Override
+ protected boolean matchesSafely(View target) {
+ Drawable currentDrawable = isBearingDrawable
+ ? mapboxMap.getMyLocationViewSettings().getForegroundBearingDrawable() :
+ mapboxMap.getMyLocationViewSettings().getForegroundDrawable();
+
+ Resources resources = target.getContext().getResources();
+ Drawable expectedDrawable = resources.getDrawable(expectedId);
+ return areDrawablesIdentical(currentDrawable, expectedDrawable);
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("trying to match MyLocationView drawable to " + expectedId);
+ }
+
+ boolean areDrawablesIdentical(Drawable drawableA, Drawable drawableB) {
+ Drawable.ConstantState stateA = drawableA.getConstantState();
+ Drawable.ConstantState stateB = drawableB.getConstantState();
+ return (stateA != null && stateB != null && stateA.equals(stateB))
+ || getBitmap(drawableA).sameAs(getBitmap(drawableB));
+ }
+
+ Bitmap getBitmap(Drawable drawable) {
+ Bitmap result;
+ if (drawable instanceof BitmapDrawable) {
+ result = ((BitmapDrawable) drawable).getBitmap();
+ } else {
+ int width = drawable.getIntrinsicWidth();
+ int height = drawable.getIntrinsicHeight();
+ // Some drawables have no intrinsic width - e.g. solid colours.
+ if (width <= 0) {
+ width = 1;
+ }
+ if (height <= 0) {
+ height = 1;
+ }
+
+ result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(result);
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ drawable.draw(canvas);
+ }
+ return result;
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerStyleTest.java
index d4c00c5f05..68ed5cb05d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerStyleTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerStyleTest.java
@@ -1,11 +1,10 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.testapp.style;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.BackgroundLayer;
@@ -19,118 +18,124 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.backgroundColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.backgroundOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.backgroundPattern;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for BackgroundLayer
*/
@RunWith(AndroidJUnit4.class)
public class BackgroundLayerStyleTest extends BaseStyleTest {
- private static final String TAG = BackgroundLayerStyleTest.class.getSimpleName();
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
- private BackgroundLayer layer;
+ private BackgroundLayer layer;
- private OnMapReadyIdlingResource idlingResource;
+ private OnMapReadyIdlingResource idlingResource;
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Before
- public void setup() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
- @Test
- public void testSetVisibility() {
- checkViewIsDisplayed(R.id.mapView);
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
- mapboxMap = rule.getActivity().getMapboxMap();
+ mapboxMap = rule.getActivity().getMapboxMap();
- Log.i(TAG, "Retrieving layer");
- layer = mapboxMap.getLayerAs("background");
- Log.i(TAG, "visibility");
- assertNotNull(layer);
+ Timber.i("Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Timber.i("visibility");
+ assertNotNull(layer);
- //Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
- //Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
- @Test
- public void testBackgroundColor() {
- checkViewIsDisplayed(R.id.mapView);
+ @Test
+ public void testBackgroundColor() {
+ checkViewIsDisplayed(R.id.mapView);
- mapboxMap = rule.getActivity().getMapboxMap();
+ mapboxMap = rule.getActivity().getMapboxMap();
- Log.i(TAG, "Retrieving layer");
- layer = mapboxMap.getLayerAs("background");
- Log.i(TAG, "background-color");
- assertNotNull(layer);
+ Timber.i("Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Timber.i("background-color");
+ assertNotNull(layer);
- //Set and Get
- layer.setProperties(backgroundColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getBackgroundColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ //Set and Get
+ layer.setProperties(backgroundColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getBackgroundColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
- @Test
- public void testBackgroundColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
+ @Test
+ public void testBackgroundColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
- mapboxMap = rule.getActivity().getMapboxMap();
+ mapboxMap = rule.getActivity().getMapboxMap();
- Log.i(TAG, "Retrieving layer");
- layer = mapboxMap.getLayerAs("background");
- Log.i(TAG, "background-color");
- assertNotNull(layer);
+ Timber.i("Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Timber.i("background-color");
+ assertNotNull(layer);
- //Set and Get
- layer.setProperties(backgroundColor(Color.RED));
- assertEquals(layer.getBackgroundColorAsInt(), Color.RED);
- }
+ //Set and Get
+ layer.setProperties(backgroundColor(Color.RED));
+ assertEquals(layer.getBackgroundColorAsInt(), Color.RED);
+ }
- @Test
- public void testBackgroundPattern() {
- checkViewIsDisplayed(R.id.mapView);
+ @Test
+ public void testBackgroundPattern() {
+ checkViewIsDisplayed(R.id.mapView);
- mapboxMap = rule.getActivity().getMapboxMap();
+ mapboxMap = rule.getActivity().getMapboxMap();
- Log.i(TAG, "Retrieving layer");
- layer = mapboxMap.getLayerAs("background");
- Log.i(TAG, "background-pattern");
- assertNotNull(layer);
+ Timber.i("Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Timber.i("background-pattern");
+ assertNotNull(layer);
- //Set and Get
- layer.setProperties(backgroundPattern("pedestrian-polygon"));
- assertEquals((String) layer.getBackgroundPattern().getValue(), (String) "pedestrian-polygon");
- }
+ //Set and Get
+ layer.setProperties(backgroundPattern("pedestrian-polygon"));
+ assertEquals((String) layer.getBackgroundPattern().getValue(), (String) "pedestrian-polygon");
+ }
- @Test
- public void testBackgroundOpacity() {
- checkViewIsDisplayed(R.id.mapView);
+ @Test
+ public void testBackgroundOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
- mapboxMap = rule.getActivity().getMapboxMap();
+ mapboxMap = rule.getActivity().getMapboxMap();
- Log.i(TAG, "Retrieving layer");
- layer = mapboxMap.getLayerAs("background");
- Log.i(TAG, "background-opacity");
- assertNotNull(layer);
+ Timber.i("Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Timber.i("background-opacity");
+ assertNotNull(layer);
- //Set and Get
- layer.setProperties(backgroundOpacity(0.3f));
- assertEquals((Float) layer.getBackgroundOpacity().getValue(), (Float) 0.3f);
- }
+ //Set and Get
+ layer.setProperties(backgroundOpacity(0.3f));
+ assertEquals((Float) layer.getBackgroundOpacity().getValue(), (Float) 0.3f);
+ }
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java
index b56c8f648f..ab53ae0487 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java
@@ -1,11 +1,10 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.testapp.style;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.BackgroundLayer;
@@ -19,118 +18,124 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.backgroundColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.backgroundOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.backgroundPattern;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for BackgroundLayer
*/
@RunWith(AndroidJUnit4.class)
public class BackgroundLayerTest extends BaseStyleTest {
- private static final String TAG = BackgroundLayerTest.class.getSimpleName();
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
- private BackgroundLayer layer;
+ private BackgroundLayer layer;
- private OnMapReadyIdlingResource idlingResource;
+ private OnMapReadyIdlingResource idlingResource;
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Before
- public void setup() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
- @Test
- public void testSetVisibility() {
- checkViewIsDisplayed(R.id.mapView);
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
- mapboxMap = rule.getActivity().getMapboxMap();
+ mapboxMap = rule.getActivity().getMapboxMap();
- Log.i(TAG, "Retrieving layer");
- layer = mapboxMap.getLayerAs("background");
- Log.i(TAG, "visibility");
- assertNotNull(layer);
+ Timber.i("Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Timber.i("visibility");
+ assertNotNull(layer);
- //Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
- //Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
- @Test
- public void testBackgroundColor() {
- checkViewIsDisplayed(R.id.mapView);
+ @Test
+ public void testBackgroundColor() {
+ checkViewIsDisplayed(R.id.mapView);
- mapboxMap = rule.getActivity().getMapboxMap();
+ mapboxMap = rule.getActivity().getMapboxMap();
- Log.i(TAG, "Retrieving layer");
- layer = mapboxMap.getLayerAs("background");
- Log.i(TAG, "background-color");
- assertNotNull(layer);
+ Timber.i("Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Timber.i("background-color");
+ assertNotNull(layer);
- //Set and Get
- layer.setProperties(backgroundColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getBackgroundColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ //Set and Get
+ layer.setProperties(backgroundColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getBackgroundColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
- @Test
- public void testBackgroundColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
+ @Test
+ public void testBackgroundColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
- mapboxMap = rule.getActivity().getMapboxMap();
+ mapboxMap = rule.getActivity().getMapboxMap();
- Log.i(TAG, "Retrieving layer");
- layer = mapboxMap.getLayerAs("background");
- Log.i(TAG, "background-color");
- assertNotNull(layer);
+ Timber.i("Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Timber.i("background-color");
+ assertNotNull(layer);
- //Set and Get
- layer.setProperties(backgroundColor(Color.RED));
- assertEquals(layer.getBackgroundColorAsInt(), Color.RED);
- }
+ //Set and Get
+ layer.setProperties(backgroundColor(Color.RED));
+ assertEquals(layer.getBackgroundColorAsInt(), Color.RED);
+ }
- @Test
- public void testBackgroundPattern() {
- checkViewIsDisplayed(R.id.mapView);
+ @Test
+ public void testBackgroundPattern() {
+ checkViewIsDisplayed(R.id.mapView);
- mapboxMap = rule.getActivity().getMapboxMap();
+ mapboxMap = rule.getActivity().getMapboxMap();
- Log.i(TAG, "Retrieving layer");
- layer = mapboxMap.getLayerAs("background");
- Log.i(TAG, "background-pattern");
- assertNotNull(layer);
+ Timber.i("Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Timber.i("background-pattern");
+ assertNotNull(layer);
- //Set and Get
- layer.setProperties(backgroundPattern("pedestrian-polygon"));
- assertEquals((String) layer.getBackgroundPattern().getValue(), (String) "pedestrian-polygon");
- }
+ //Set and Get
+ layer.setProperties(backgroundPattern("pedestrian-polygon"));
+ assertEquals((String) layer.getBackgroundPattern().getValue(), (String) "pedestrian-polygon");
+ }
- @Test
- public void testBackgroundOpacity() {
- checkViewIsDisplayed(R.id.mapView);
+ @Test
+ public void testBackgroundOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
- mapboxMap = rule.getActivity().getMapboxMap();
+ mapboxMap = rule.getActivity().getMapboxMap();
- Log.i(TAG, "Retrieving layer");
- layer = mapboxMap.getLayerAs("background");
- Log.i(TAG, "background-opacity");
- assertNotNull(layer);
+ Timber.i("Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Timber.i("background-opacity");
+ assertNotNull(layer);
- //Set and Get
- layer.setProperties(backgroundOpacity(0.3f));
- assertEquals((Float) layer.getBackgroundOpacity().getValue(), (Float) 0.3f);
- }
+ //Set and Get
+ layer.setProperties(backgroundOpacity(0.3f));
+ assertEquals((Float) layer.getBackgroundOpacity().getValue(), (Float) 0.3f);
+ }
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BaseStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BaseStyleTest.java
index 5ec4e5437b..620e15579f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BaseStyleTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BaseStyleTest.java
@@ -14,31 +14,31 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId;
*/
public class BaseStyleTest {
- protected final static String HOME_BUTTON_STRING = "Navigate up";
+ protected static final String HOME_BUTTON_STRING = "Navigate up";
- /*
- * Shortcuts for common UI tests
- */
+ /*
+ * Shortcuts for common UI tests
+ */
- protected void checkViewIsDisplayed(int id) {
- onView(withId(id))
- .check(matches(isDisplayed()));
- }
+ protected void checkViewIsDisplayed(int id) {
+ onView(withId(id))
+ .check(matches(isDisplayed()));
+ }
- /*
- * Screenshots logic
- */
+ /*
+ * Screenshots logic
+ */
- protected void takeNamedScreenshot(final Activity activity, final String name) {
+ protected void takeNamedScreenshot(final Activity activity, final String name) {
- // Screenshots need to be taken on the UI thread
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- ScreenshotUtil.take(activity, name);
- }
- });
+ // Screenshots need to be taken on the UI thread
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ ScreenshotUtil.take(activity, name);
+ }
+ });
- }
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerStyleTest.java
index a7301962d1..58fda51f07 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerStyleTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerStyleTest.java
@@ -1,11 +1,10 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.testapp.style;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
@@ -19,236 +18,248 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.Property.CIRCLE_PITCH_SCALE_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.CIRCLE_TRANSLATE_ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleBlur;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circlePitchScale;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for CircleLayer
*/
@RunWith(AndroidJUnit4.class)
public class CircleLayerStyleTest extends BaseStyleTest {
- private static final String TAG = CircleLayerStyleTest.class.getSimpleName();
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
- private CircleLayer layer;
+ private CircleLayer layer;
- private OnMapReadyIdlingResource idlingResource;
+ private OnMapReadyIdlingResource idlingResource;
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Before
- public void setup() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
- @Test
- public void testSetVisibility() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "visibility");
- assertNotNull(layer);
-
- //Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
-
- //Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
- @Test
- public void testCircleRadius() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-radius");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleRadius(0.3f));
- assertEquals((Float) layer.getCircleRadius().getValue(), (Float) 0.3f);
- }
+ mapboxMap = rule.getActivity().getMapboxMap();
- @Test
- public void testCircleColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getCircleColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testCircleColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleColor(Color.RED));
- assertEquals(layer.getCircleColorAsInt(), Color.RED);
+ Timber.i("visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testCircleRadius() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testCircleBlur() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-blur");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleBlur(0.3f));
- assertEquals((Float) layer.getCircleBlur().getValue(), (Float) 0.3f);
+ Timber.i("circle-radius");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleRadius(0.3f));
+ assertEquals((Float) layer.getCircleRadius().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testCircleColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testCircleOpacity() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-opacity");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleOpacity(0.3f));
- assertEquals((Float) layer.getCircleOpacity().getValue(), (Float) 0.3f);
+ Timber.i("circle-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getCircleColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testCircleColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testCircleTranslate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-translate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleTranslate(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getCircleTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("circle-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleColor(Color.RED));
+ assertEquals(layer.getCircleColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testCircleBlur() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testCircleTranslateAnchor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-translate-anchor");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleTranslateAnchor(CIRCLE_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getCircleTranslateAnchor().getValue(), (String) CIRCLE_TRANSLATE_ANCHOR_MAP);
+ Timber.i("circle-blur");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleBlur(0.3f));
+ assertEquals((Float) layer.getCircleBlur().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testCircleOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testCirclePitchScale() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-pitch-scale");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circlePitchScale(CIRCLE_PITCH_SCALE_MAP));
- assertEquals((String) layer.getCirclePitchScale().getValue(), (String) CIRCLE_PITCH_SCALE_MAP);
+ Timber.i("circle-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleOpacity(0.3f));
+ assertEquals((Float) layer.getCircleOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testCircleTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
+ Timber.i("circle-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getCircleTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testCircleTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("circle-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleTranslateAnchor(CIRCLE_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getCircleTranslateAnchor().getValue(), (String) CIRCLE_TRANSLATE_ANCHOR_MAP);
+ }
+
+ @Test
+ public void testCirclePitchScale() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("circle-pitch-scale");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circlePitchScale(CIRCLE_PITCH_SCALE_MAP));
+ assertEquals((String) layer.getCirclePitchScale().getValue(), (String) CIRCLE_PITCH_SCALE_MAP);
+ }
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
index 8b0f1af17b..782598a0b2 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
@@ -1,11 +1,10 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.testapp.style;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
@@ -19,236 +18,339 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.Property.CIRCLE_PITCH_SCALE_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.CIRCLE_TRANSLATE_ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleBlur;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circlePitchScale;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleStrokeColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleStrokeOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleStrokeWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for CircleLayer
*/
@RunWith(AndroidJUnit4.class)
public class CircleLayerTest extends BaseStyleTest {
- private static final String TAG = CircleLayerTest.class.getSimpleName();
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
- private CircleLayer layer;
+ private CircleLayer layer;
- private OnMapReadyIdlingResource idlingResource;
+ private OnMapReadyIdlingResource idlingResource;
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Before
- public void setup() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
- @Test
- public void testSetVisibility() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "visibility");
- assertNotNull(layer);
-
- //Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
-
- //Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
- @Test
- public void testCircleRadius() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-radius");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleRadius(0.3f));
- assertEquals((Float) layer.getCircleRadius().getValue(), (Float) 0.3f);
- }
+ mapboxMap = rule.getActivity().getMapboxMap();
- @Test
- public void testCircleColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getCircleColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testCircleColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleColor(Color.RED));
- assertEquals(layer.getCircleColorAsInt(), Color.RED);
+ Timber.i("visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testCircleRadius() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testCircleBlur() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-blur");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleBlur(0.3f));
- assertEquals((Float) layer.getCircleBlur().getValue(), (Float) 0.3f);
+ Timber.i("circle-radius");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleRadius(0.3f));
+ assertEquals((Float) layer.getCircleRadius().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testCircleColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testCircleOpacity() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-opacity");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleOpacity(0.3f));
- assertEquals((Float) layer.getCircleOpacity().getValue(), (Float) 0.3f);
+ Timber.i("circle-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getCircleColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testCircleColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testCircleTranslate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-translate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleTranslate(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getCircleTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("circle-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleColor(Color.RED));
+ assertEquals(layer.getCircleColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testCircleBlur() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testCircleTranslateAnchor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-translate-anchor");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circleTranslateAnchor(CIRCLE_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getCircleTranslateAnchor().getValue(), (String) CIRCLE_TRANSLATE_ANCHOR_MAP);
+ Timber.i("circle-blur");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleBlur(0.3f));
+ assertEquals((Float) layer.getCircleBlur().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testCircleOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testCirclePitchScale() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "circle-pitch-scale");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(circlePitchScale(CIRCLE_PITCH_SCALE_MAP));
- assertEquals((String) layer.getCirclePitchScale().getValue(), (String) CIRCLE_PITCH_SCALE_MAP);
+ Timber.i("circle-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleOpacity(0.3f));
+ assertEquals((Float) layer.getCircleOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testCircleTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("circle-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getCircleTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testCircleTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("circle-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleTranslateAnchor(CIRCLE_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getCircleTranslateAnchor().getValue(), (String) CIRCLE_TRANSLATE_ANCHOR_MAP);
+ }
+
+ @Test
+ public void testCirclePitchScale() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("circle-pitch-scale");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circlePitchScale(CIRCLE_PITCH_SCALE_MAP));
+ assertEquals((String) layer.getCirclePitchScale().getValue(), (String) CIRCLE_PITCH_SCALE_MAP);
+ }
+
+ @Test
+ public void testCircleStrokeWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
+ Timber.i("circle-stroke-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleStrokeWidth(0.3f));
+ assertEquals((Float) layer.getCircleStrokeWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testCircleStrokeColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("circle-stroke-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleStrokeColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getCircleStrokeColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testCircleStrokeColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("circle-stroke-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleStrokeColor(Color.RED));
+ assertEquals(layer.getCircleStrokeColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testCircleStrokeOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("circle-stroke-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleStrokeOpacity(0.3f));
+ assertEquals((Float) layer.getCircleStrokeOpacity().getValue(), (Float) 0.3f);
+ }
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerStyleTest.java
index 46ad1da879..c8668fa407 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerStyleTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerStyleTest.java
@@ -1,11 +1,10 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.testapp.style;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
@@ -19,258 +18,269 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.Property.FILL_TRANSLATE_ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillAntialias;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillOutlineColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillPattern;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for FillLayer
*/
@RunWith(AndroidJUnit4.class)
public class FillLayerStyleTest extends BaseStyleTest {
- private static final String TAG = FillLayerStyleTest.class.getSimpleName();
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
- private FillLayer layer;
+ private FillLayer layer;
- private OnMapReadyIdlingResource idlingResource;
+ private OnMapReadyIdlingResource idlingResource;
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Before
- public void setup() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
- @Test
- public void testSetVisibility() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "visibility");
- assertNotNull(layer);
-
- //Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
-
- //Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
- @Test
- public void testFillAntialias() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-antialias");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillAntialias(true));
- assertEquals((Boolean) layer.getFillAntialias().getValue(), (Boolean) true);
- }
+ mapboxMap = rule.getActivity().getMapboxMap();
- @Test
- public void testFillOpacity() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-opacity");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillOpacity(0.3f));
- assertEquals((Float) layer.getFillOpacity().getValue(), (Float) 0.3f);
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getFillColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testFillAntialias() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillColor(Color.RED));
- assertEquals(layer.getFillColorAsInt(), Color.RED);
+ Timber.i("fill-antialias");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillAntialias(true));
+ assertEquals((Boolean) layer.getFillAntialias().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testFillOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillOutlineColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-outline-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillOutlineColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getFillOutlineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("fill-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillOpacity(0.3f));
+ assertEquals((Float) layer.getFillOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testFillColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillOutlineColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-outline-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillOutlineColor(Color.RED));
- assertEquals(layer.getFillOutlineColorAsInt(), Color.RED);
+ Timber.i("fill-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getFillColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testFillColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillTranslate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-translate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillTranslate(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getFillTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("fill-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillColor(Color.RED));
+ assertEquals(layer.getFillColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testFillOutlineColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillTranslateAnchor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-translate-anchor");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getFillTranslateAnchor().getValue(), (String) FILL_TRANSLATE_ANCHOR_MAP);
+ Timber.i("fill-outline-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillOutlineColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getFillOutlineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testFillOutlineColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillPattern() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-pattern");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillPattern("pedestrian-polygon"));
- assertEquals((String) layer.getFillPattern().getValue(), (String) "pedestrian-polygon");
+ Timber.i("fill-outline-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillOutlineColor(Color.RED));
+ assertEquals(layer.getFillOutlineColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testFillTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
+ Timber.i("fill-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getFillTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testFillTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("fill-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getFillTranslateAnchor().getValue(), (String) FILL_TRANSLATE_ANCHOR_MAP);
+ }
+
+ @Test
+ public void testFillPattern() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("fill-pattern");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillPattern("pedestrian-polygon"));
+ assertEquals((String) layer.getFillPattern().getValue(), (String) "pedestrian-polygon");
+ }
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java
index 593d444bc4..95360e1273 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java
@@ -1,11 +1,10 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.testapp.style;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
@@ -19,258 +18,269 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.Property.FILL_TRANSLATE_ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillAntialias;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillOutlineColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillPattern;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for FillLayer
*/
@RunWith(AndroidJUnit4.class)
public class FillLayerTest extends BaseStyleTest {
- private static final String TAG = FillLayerTest.class.getSimpleName();
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
- private FillLayer layer;
+ private FillLayer layer;
- private OnMapReadyIdlingResource idlingResource;
+ private OnMapReadyIdlingResource idlingResource;
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Before
- public void setup() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
- @Test
- public void testSetVisibility() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "visibility");
- assertNotNull(layer);
-
- //Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
-
- //Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
- @Test
- public void testFillAntialias() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-antialias");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillAntialias(true));
- assertEquals((Boolean) layer.getFillAntialias().getValue(), (Boolean) true);
- }
+ mapboxMap = rule.getActivity().getMapboxMap();
- @Test
- public void testFillOpacity() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-opacity");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillOpacity(0.3f));
- assertEquals((Float) layer.getFillOpacity().getValue(), (Float) 0.3f);
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getFillColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testFillAntialias() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillColor(Color.RED));
- assertEquals(layer.getFillColorAsInt(), Color.RED);
+ Timber.i("fill-antialias");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillAntialias(true));
+ assertEquals((Boolean) layer.getFillAntialias().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testFillOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillOutlineColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-outline-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillOutlineColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getFillOutlineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("fill-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillOpacity(0.3f));
+ assertEquals((Float) layer.getFillOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testFillColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillOutlineColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-outline-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillOutlineColor(Color.RED));
- assertEquals(layer.getFillOutlineColorAsInt(), Color.RED);
+ Timber.i("fill-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getFillColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testFillColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillTranslate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-translate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillTranslate(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getFillTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("fill-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillColor(Color.RED));
+ assertEquals(layer.getFillColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testFillOutlineColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillTranslateAnchor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-translate-anchor");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getFillTranslateAnchor().getValue(), (String) FILL_TRANSLATE_ANCHOR_MAP);
+ Timber.i("fill-outline-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillOutlineColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getFillOutlineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testFillOutlineColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testFillPattern() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "fill-pattern");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(fillPattern("pedestrian-polygon"));
- assertEquals((String) layer.getFillPattern().getValue(), (String) "pedestrian-polygon");
+ Timber.i("fill-outline-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillOutlineColor(Color.RED));
+ assertEquals(layer.getFillOutlineColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testFillTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
+ Timber.i("fill-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getFillTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testFillTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("fill-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getFillTranslateAnchor().getValue(), (String) FILL_TRANSLATE_ANCHOR_MAP);
+ }
+
+ @Test
+ public void testFillPattern() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("fill-pattern");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillPattern("pedestrian-polygon"));
+ assertEquals((String) layer.getFillPattern().getValue(), (String) "pedestrian-polygon");
+ }
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerStyleTest.java
index 09c1ae797d..47a38a11ab 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerStyleTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerStyleTest.java
@@ -1,11 +1,10 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.testapp.style;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.LineLayer;
@@ -19,390 +18,410 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.Property.LINE_CAP_BUTT;
+import static com.mapbox.mapboxsdk.style.layers.Property.LINE_JOIN_BEVEL;
+import static com.mapbox.mapboxsdk.style.layers.Property.LINE_TRANSLATE_ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineBlur;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineCap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineDasharray;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineGapWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineJoin;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineMiterLimit;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineOffset;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.linePattern;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineRoundLimit;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for LineLayer
*/
@RunWith(AndroidJUnit4.class)
public class LineLayerStyleTest extends BaseStyleTest {
- private static final String TAG = LineLayerStyleTest.class.getSimpleName();
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
- private LineLayer layer;
+ private LineLayer layer;
- private OnMapReadyIdlingResource idlingResource;
+ private OnMapReadyIdlingResource idlingResource;
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Before
- public void setup() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
- @Test
- public void testSetVisibility() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "visibility");
- assertNotNull(layer);
-
- //Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
-
- //Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
- @Test
- public void testLineCap() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-cap");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineCap(LINE_CAP_BUTT));
- assertEquals((String) layer.getLineCap().getValue(), (String) LINE_CAP_BUTT);
- }
+ mapboxMap = rule.getActivity().getMapboxMap();
- @Test
- public void testLineJoin() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-join");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineJoin(LINE_JOIN_BEVEL));
- assertEquals((String) layer.getLineJoin().getValue(), (String) LINE_JOIN_BEVEL);
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineMiterLimit() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-miter-limit");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineMiterLimit(0.3f));
- assertEquals((Float) layer.getLineMiterLimit().getValue(), (Float) 0.3f);
+ Timber.i("visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testLineCap() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineRoundLimit() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-round-limit");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineRoundLimit(0.3f));
- assertEquals((Float) layer.getLineRoundLimit().getValue(), (Float) 0.3f);
+ Timber.i("line-cap");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineCap(LINE_CAP_BUTT));
+ assertEquals((String) layer.getLineCap().getValue(), (String) LINE_CAP_BUTT);
+ }
+
+ @Test
+ public void testLineJoin() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineOpacity() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-opacity");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineOpacity(0.3f));
- assertEquals((Float) layer.getLineOpacity().getValue(), (Float) 0.3f);
+ Timber.i("line-join");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineJoin(LINE_JOIN_BEVEL));
+ assertEquals((String) layer.getLineJoin().getValue(), (String) LINE_JOIN_BEVEL);
+ }
+
+ @Test
+ public void testLineMiterLimit() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getLineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("line-miter-limit");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineMiterLimit(0.3f));
+ assertEquals((Float) layer.getLineMiterLimit().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineRoundLimit() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineColor(Color.RED));
- assertEquals(layer.getLineColorAsInt(), Color.RED);
+ Timber.i("line-round-limit");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineRoundLimit(0.3f));
+ assertEquals((Float) layer.getLineRoundLimit().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineTranslate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-translate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineTranslate(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getLineTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("line-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineOpacity(0.3f));
+ assertEquals((Float) layer.getLineOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineTranslateAnchor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-translate-anchor");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineTranslateAnchor(LINE_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getLineTranslateAnchor().getValue(), (String) LINE_TRANSLATE_ANCHOR_MAP);
+ Timber.i("line-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getLineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testLineColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineWidth() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-width");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineWidth(0.3f));
- assertEquals((Float) layer.getLineWidth().getValue(), (Float) 0.3f);
+ Timber.i("line-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineColor(Color.RED));
+ assertEquals(layer.getLineColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testLineTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineGapWidth() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-gap-width");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineGapWidth(0.3f));
- assertEquals((Float) layer.getLineGapWidth().getValue(), (Float) 0.3f);
+ Timber.i("line-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getLineTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testLineTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineOffset() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-offset");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineOffset(0.3f));
- assertEquals((Float) layer.getLineOffset().getValue(), (Float) 0.3f);
+ Timber.i("line-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineTranslateAnchor(LINE_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getLineTranslateAnchor().getValue(), (String) LINE_TRANSLATE_ANCHOR_MAP);
+ }
+
+ @Test
+ public void testLineWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineBlur() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-blur");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineBlur(0.3f));
- assertEquals((Float) layer.getLineBlur().getValue(), (Float) 0.3f);
+ Timber.i("line-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineWidth(0.3f));
+ assertEquals((Float) layer.getLineWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineGapWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineDasharray() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-dasharray");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineDasharray(new Float[]{}));
- assertEquals((Float[]) layer.getLineDasharray().getValue(), (Float[]) new Float[]{});
+ Timber.i("line-gap-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineGapWidth(0.3f));
+ assertEquals((Float) layer.getLineGapWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineOffset() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLinePattern() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-pattern");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(linePattern("pedestrian-polygon"));
- assertEquals((String) layer.getLinePattern().getValue(), (String) "pedestrian-polygon");
+ Timber.i("line-offset");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineOffset(0.3f));
+ assertEquals((Float) layer.getLineOffset().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineBlur() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("line-blur");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineBlur(0.3f));
+ assertEquals((Float) layer.getLineBlur().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineDasharray() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
+ Timber.i("line-dasharray");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineDasharray(new Float[] {}));
+ assertEquals((Float[]) layer.getLineDasharray().getValue(), (Float[]) new Float[] {});
+ }
+
+ @Test
+ public void testLinePattern() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("line-pattern");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(linePattern("pedestrian-polygon"));
+ assertEquals((String) layer.getLinePattern().getValue(), (String) "pedestrian-polygon");
+ }
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
index 15fd35f0a8..ad091c78b3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
@@ -1,11 +1,10 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.testapp.style;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.LineLayer;
@@ -19,390 +18,410 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.Property.LINE_CAP_BUTT;
+import static com.mapbox.mapboxsdk.style.layers.Property.LINE_JOIN_BEVEL;
+import static com.mapbox.mapboxsdk.style.layers.Property.LINE_TRANSLATE_ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineBlur;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineCap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineDasharray;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineGapWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineJoin;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineMiterLimit;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineOffset;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.linePattern;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineRoundLimit;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for LineLayer
*/
@RunWith(AndroidJUnit4.class)
public class LineLayerTest extends BaseStyleTest {
- private static final String TAG = LineLayerTest.class.getSimpleName();
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
- private LineLayer layer;
+ private LineLayer layer;
- private OnMapReadyIdlingResource idlingResource;
+ private OnMapReadyIdlingResource idlingResource;
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Before
- public void setup() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
- @Test
- public void testSetVisibility() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "visibility");
- assertNotNull(layer);
-
- //Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
-
- //Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
- @Test
- public void testLineCap() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-cap");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineCap(LINE_CAP_BUTT));
- assertEquals((String) layer.getLineCap().getValue(), (String) LINE_CAP_BUTT);
- }
+ mapboxMap = rule.getActivity().getMapboxMap();
- @Test
- public void testLineJoin() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-join");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineJoin(LINE_JOIN_BEVEL));
- assertEquals((String) layer.getLineJoin().getValue(), (String) LINE_JOIN_BEVEL);
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineMiterLimit() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-miter-limit");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineMiterLimit(0.3f));
- assertEquals((Float) layer.getLineMiterLimit().getValue(), (Float) 0.3f);
+ Timber.i("visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testLineCap() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineRoundLimit() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-round-limit");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineRoundLimit(0.3f));
- assertEquals((Float) layer.getLineRoundLimit().getValue(), (Float) 0.3f);
+ Timber.i("line-cap");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineCap(LINE_CAP_BUTT));
+ assertEquals((String) layer.getLineCap().getValue(), (String) LINE_CAP_BUTT);
+ }
+
+ @Test
+ public void testLineJoin() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineOpacity() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-opacity");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineOpacity(0.3f));
- assertEquals((Float) layer.getLineOpacity().getValue(), (Float) 0.3f);
+ Timber.i("line-join");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineJoin(LINE_JOIN_BEVEL));
+ assertEquals((String) layer.getLineJoin().getValue(), (String) LINE_JOIN_BEVEL);
+ }
+
+ @Test
+ public void testLineMiterLimit() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getLineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("line-miter-limit");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineMiterLimit(0.3f));
+ assertEquals((Float) layer.getLineMiterLimit().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineRoundLimit() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineColor(Color.RED));
- assertEquals(layer.getLineColorAsInt(), Color.RED);
+ Timber.i("line-round-limit");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineRoundLimit(0.3f));
+ assertEquals((Float) layer.getLineRoundLimit().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineTranslate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-translate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineTranslate(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getLineTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("line-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineOpacity(0.3f));
+ assertEquals((Float) layer.getLineOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineTranslateAnchor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-translate-anchor");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineTranslateAnchor(LINE_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getLineTranslateAnchor().getValue(), (String) LINE_TRANSLATE_ANCHOR_MAP);
+ Timber.i("line-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getLineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testLineColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineWidth() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-width");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineWidth(0.3f));
- assertEquals((Float) layer.getLineWidth().getValue(), (Float) 0.3f);
+ Timber.i("line-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineColor(Color.RED));
+ assertEquals(layer.getLineColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testLineTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineGapWidth() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-gap-width");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineGapWidth(0.3f));
- assertEquals((Float) layer.getLineGapWidth().getValue(), (Float) 0.3f);
+ Timber.i("line-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getLineTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testLineTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineOffset() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-offset");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineOffset(0.3f));
- assertEquals((Float) layer.getLineOffset().getValue(), (Float) 0.3f);
+ Timber.i("line-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineTranslateAnchor(LINE_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getLineTranslateAnchor().getValue(), (String) LINE_TRANSLATE_ANCHOR_MAP);
+ }
+
+ @Test
+ public void testLineWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineBlur() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-blur");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineBlur(0.3f));
- assertEquals((Float) layer.getLineBlur().getValue(), (Float) 0.3f);
+ Timber.i("line-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineWidth(0.3f));
+ assertEquals((Float) layer.getLineWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineGapWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLineDasharray() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-dasharray");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(lineDasharray(new Float[]{}));
- assertEquals((Float[]) layer.getLineDasharray().getValue(), (Float[]) new Float[]{});
+ Timber.i("line-gap-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineGapWidth(0.3f));
+ assertEquals((Float) layer.getLineGapWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineOffset() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testLinePattern() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "line-pattern");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(linePattern("pedestrian-polygon"));
- assertEquals((String) layer.getLinePattern().getValue(), (String) "pedestrian-polygon");
+ Timber.i("line-offset");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineOffset(0.3f));
+ assertEquals((Float) layer.getLineOffset().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineBlur() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("line-blur");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineBlur(0.3f));
+ assertEquals((Float) layer.getLineBlur().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineDasharray() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
+ Timber.i("line-dasharray");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineDasharray(new Float[] {}));
+ assertEquals((Float[]) layer.getLineDasharray().getValue(), (Float[]) new Float[] {});
+ }
+
+ @Test
+ public void testLinePattern() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("line-pattern");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(linePattern("pedestrian-polygon"));
+ assertEquals((String) layer.getLinePattern().getValue(), (String) "pedestrian-polygon");
+ }
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerStyleTest.java
index 2baddd6fa1..eb67b48f7a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerStyleTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerStyleTest.java
@@ -1,10 +1,9 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.testapp.style;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.RasterLayer;
@@ -18,214 +17,224 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterBrightnessMax;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterBrightnessMin;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterContrast;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterFadeDuration;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterHueRotate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterSaturation;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for RasterLayer
*/
@RunWith(AndroidJUnit4.class)
public class RasterLayerStyleTest extends BaseStyleTest {
- private static final String TAG = RasterLayerStyleTest.class.getSimpleName();
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
- private RasterLayer layer;
+ private RasterLayer layer;
- private OnMapReadyIdlingResource idlingResource;
+ private OnMapReadyIdlingResource idlingResource;
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Before
- public void setup() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
- @Test
- public void testSetVisibility() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "visibility");
- assertNotNull(layer);
-
- //Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
-
- //Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
- @Test
- public void testRasterOpacity() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-opacity");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterOpacity(0.3f));
- assertEquals((Float) layer.getRasterOpacity().getValue(), (Float) 0.3f);
- }
+ mapboxMap = rule.getActivity().getMapboxMap();
- @Test
- public void testRasterHueRotate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-hue-rotate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterHueRotate(0.3f));
- assertEquals((Float) layer.getRasterHueRotate().getValue(), (Float) 0.3f);
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testRasterBrightnessMin() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-brightness-min");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterBrightnessMin(0.3f));
- assertEquals((Float) layer.getRasterBrightnessMin().getValue(), (Float) 0.3f);
+ Timber.i("visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testRasterOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testRasterBrightnessMax() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-brightness-max");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterBrightnessMax(0.3f));
- assertEquals((Float) layer.getRasterBrightnessMax().getValue(), (Float) 0.3f);
+ Timber.i("raster-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterOpacity(0.3f));
+ assertEquals((Float) layer.getRasterOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterHueRotate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testRasterSaturation() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-saturation");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterSaturation(0.3f));
- assertEquals((Float) layer.getRasterSaturation().getValue(), (Float) 0.3f);
+ Timber.i("raster-hue-rotate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterHueRotate(0.3f));
+ assertEquals((Float) layer.getRasterHueRotate().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterBrightnessMin() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testRasterContrast() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-contrast");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterContrast(0.3f));
- assertEquals((Float) layer.getRasterContrast().getValue(), (Float) 0.3f);
+ Timber.i("raster-brightness-min");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterBrightnessMin(0.3f));
+ assertEquals((Float) layer.getRasterBrightnessMin().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterBrightnessMax() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testRasterFadeDuration() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-fade-duration");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterFadeDuration(0.3f));
- assertEquals((Float) layer.getRasterFadeDuration().getValue(), (Float) 0.3f);
+ Timber.i("raster-brightness-max");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterBrightnessMax(0.3f));
+ assertEquals((Float) layer.getRasterBrightnessMax().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterSaturation() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
+ Timber.i("raster-saturation");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterSaturation(0.3f));
+ assertEquals((Float) layer.getRasterSaturation().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterContrast() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("raster-contrast");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterContrast(0.3f));
+ assertEquals((Float) layer.getRasterContrast().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterFadeDuration() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("raster-fade-duration");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterFadeDuration(0.3f));
+ assertEquals((Float) layer.getRasterFadeDuration().getValue(), (Float) 0.3f);
+ }
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java
index b64c9a244c..169d747b9c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java
@@ -1,11 +1,9 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.testapp.style;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
-import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.RasterLayer;
@@ -19,214 +17,224 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterBrightnessMax;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterBrightnessMin;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterContrast;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterFadeDuration;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterHueRotate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterSaturation;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for RasterLayer
*/
@RunWith(AndroidJUnit4.class)
public class RasterLayerTest extends BaseStyleTest {
- private static final String TAG = RasterLayerTest.class.getSimpleName();
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
- private RasterLayer layer;
+ private RasterLayer layer;
- private OnMapReadyIdlingResource idlingResource;
+ private OnMapReadyIdlingResource idlingResource;
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Before
- public void setup() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
- @Test
- public void testSetVisibility() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "visibility");
- assertNotNull(layer);
-
- //Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
-
- //Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
- @Test
- public void testRasterOpacity() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-opacity");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterOpacity(0.3f));
- assertEquals((Float) layer.getRasterOpacity().getValue(), (Float) 0.3f);
- }
+ mapboxMap = rule.getActivity().getMapboxMap();
- @Test
- public void testRasterHueRotate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-hue-rotate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterHueRotate(0.3f));
- assertEquals((Float) layer.getRasterHueRotate().getValue(), (Float) 0.3f);
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testRasterBrightnessMin() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-brightness-min");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterBrightnessMin(0.3f));
- assertEquals((Float) layer.getRasterBrightnessMin().getValue(), (Float) 0.3f);
+ Timber.i("visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testRasterOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testRasterBrightnessMax() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-brightness-max");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterBrightnessMax(0.3f));
- assertEquals((Float) layer.getRasterBrightnessMax().getValue(), (Float) 0.3f);
+ Timber.i("raster-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterOpacity(0.3f));
+ assertEquals((Float) layer.getRasterOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterHueRotate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testRasterSaturation() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-saturation");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterSaturation(0.3f));
- assertEquals((Float) layer.getRasterSaturation().getValue(), (Float) 0.3f);
+ Timber.i("raster-hue-rotate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterHueRotate(0.3f));
+ assertEquals((Float) layer.getRasterHueRotate().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterBrightnessMin() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testRasterContrast() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-contrast");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterContrast(0.3f));
- assertEquals((Float) layer.getRasterContrast().getValue(), (Float) 0.3f);
+ Timber.i("raster-brightness-min");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterBrightnessMin(0.3f));
+ assertEquals((Float) layer.getRasterBrightnessMin().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterBrightnessMax() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testRasterFadeDuration() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "raster-fade-duration");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(rasterFadeDuration(0.3f));
- assertEquals((Float) layer.getRasterFadeDuration().getValue(), (Float) 0.3f);
+ Timber.i("raster-brightness-max");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterBrightnessMax(0.3f));
+ assertEquals((Float) layer.getRasterBrightnessMax().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterSaturation() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("raster-saturation");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterSaturation(0.3f));
+ assertEquals((Float) layer.getRasterSaturation().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterContrast() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
+ Timber.i("raster-contrast");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterContrast(0.3f));
+ assertEquals((Float) layer.getRasterContrast().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterFadeDuration() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("raster-fade-duration");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterFadeDuration(0.3f));
+ assertEquals((Float) layer.getRasterFadeDuration().getValue(), (Float) 0.3f);
+ }
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleBackgroundLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleBackgroundLayerTest.java
index f562a5d8a3..762ae4f846 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleBackgroundLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleBackgroundLayerTest.java
@@ -3,7 +3,8 @@ package com.mapbox.mapboxsdk.testapp.style;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
+
+import timber.log.Timber;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
@@ -22,40 +23,39 @@ import org.junit.runner.RunWith;
*/
@RunWith(AndroidJUnit4.class)
public class RuntimeStyleBackgroundLayerTest
- extends ActivityInstrumentationTestCase2<RuntimeStyleTestActivity> {
- private static final String TAG = RuntimeStyleBackgroundLayerTest.class.getSimpleName();
-
- public RuntimeStyleBackgroundLayerTest() {
- super(RuntimeStyleTestActivity.class);
- }
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
- injectInstrumentation(InstrumentationRegistry.getInstrumentation());
- }
-
- @Test
- public void testSetVisibility() {
- getActivity().mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap mapboxMap) {
- Log.i(TAG, "visibility");
- BackgroundLayer layer = mapboxMap.getLayerAs("background");
- assertNotNull(layer);
-
- //Get initial
- assertEquals(layer.getVisibility().getValue(), Property.VISIBLE);
-
- //Set
- layer.setProperties(PropertyFactory.visibility(Property.NONE));
- assertEquals(layer.getVisibility().getValue(), Property.NONE);
- }
- });
- }
-
- @After
- public void tearDown() throws Exception {
- super.tearDown();
- }
+ extends ActivityInstrumentationTestCase2<RuntimeStyleTestActivity> {
+
+ public RuntimeStyleBackgroundLayerTest() {
+ super(RuntimeStyleTestActivity.class);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ injectInstrumentation(InstrumentationRegistry.getInstrumentation());
+ }
+
+ @Test
+ public void testSetVisibility() {
+ getActivity().mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap mapboxMap) {
+ Timber.i("visibility");
+ BackgroundLayer layer = mapboxMap.getLayerAs("background");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), Property.VISIBLE);
+
+ //Set
+ layer.setProperties(PropertyFactory.visibility(Property.NONE));
+ assertEquals(layer.getVisibility().getValue(), Property.NONE);
+ }
+ });
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
index 783601b1dd..eec00bdde9 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
@@ -1,100 +1,201 @@
package com.mapbox.mapboxsdk.testapp.style;
+import android.graphics.Color;
import android.support.test.espresso.Espresso;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.style.layers.CannotAddLayerException;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
import com.mapbox.mapboxsdk.style.layers.NoSuchLayerException;
import com.mapbox.mapboxsdk.style.layers.Property;
import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
+import com.mapbox.mapboxsdk.style.sources.CannotAddSourceException;
import com.mapbox.mapboxsdk.style.sources.NoSuchSourceException;
+import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.mapboxsdk.style.sources.VectorSource;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+import junit.framework.Assert;
+
+import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.assertFalse;
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static junit.framework.Assert.fail;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
/**
* Basic smoke tests for Layer and Source
*/
@RunWith(AndroidJUnit4.class)
-public class RuntimeStyleTests extends BaseStyleTest {
+public class RuntimeStyleTests {
+
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testGetAddRemoveLayer() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ onView(withId(R.id.mapView)).perform(new AddRemoveLayerAction());
+ }
+
+ @Test
+ public void testAddRemoveSource() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+ mapboxMap.addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
+ try {
+ mapboxMap.removeSource("my-source");
+ } catch (NoSuchSourceException noSuchSourceException) {
+ // it's ok..
+ }
+
+ onView(withId(R.id.mapView)).perform(new AddRemoveSourceAction());
+ }
+
+ private class AddRemoveLayerAction implements ViewAction {
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
- private OnMapReadyIdlingResource idlingResource;
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
- @Before
- public void registerIdlingResource() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
+ @Override
+ public void perform(UiController uiController, View view) {
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ //Get initial
+ assertNotNull(mapboxMap.getLayer("building"));
+
+ //Remove
+ try {
+ mapboxMap.removeLayer("building");
+ } catch (NoSuchLayerException noSuchSourceException) {
+ fail("Definitively exists: " + noSuchSourceException.getMessage());
+ }
+ assertNull(mapboxMap.getLayer("building"));
+
+ //Add
+ FillLayer layer = new FillLayer("building", "composite");
+ layer.setSourceLayer("building");
+ mapboxMap.addLayer(layer);
+ assertNotNull(mapboxMap.getLayer("building"));
+
+ //Assure the reference still works
+ layer.setProperties(PropertyFactory.visibility(Property.VISIBLE));
+
+ //Remove, preserving the reference
+ try {
+ mapboxMap.removeLayer(layer);
+ } catch (NoSuchLayerException noSuchSourceException) {
+ fail("Definitively exists: " + noSuchSourceException.getMessage());
+ }
+
+ //Property setters should still work
+ layer.setProperties(PropertyFactory.fillColor(Color.RED));
+
+ //Re-add the reference...
+ mapboxMap.addLayer(layer);
+
+ //Ensure it's there
+ Assert.assertNotNull(mapboxMap.getLayer(layer.getId()));
+
+ //Test adding a duplicate layer
+ try {
+ mapboxMap.addLayer(new FillLayer("building", "composite"));
+ fail("Should not have been allowed to add a layer with a duplicate id");
+ } catch (CannotAddLayerException cannotAddLayerException) {
+ //OK
+ }
}
+ }
- /**
- * TODO fix failing test
- */
- @Test
- @Ignore
- public void testGetAddRemoveLayer() {
- checkViewIsDisplayed(R.id.mapView);
-
- MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
-
- //Get initial
- assertNotNull(mapboxMap.getLayer("building"));
-
- //Remove
- try {
- mapboxMap.removeLayer("building");
- } catch (NoSuchLayerException e) {
- assertFalse(true);
- }
- assertNull(mapboxMap.getLayer("building"));
-
- //Add
- FillLayer layer = new FillLayer("building", "composite");
- layer.setSourceLayer("building");
- mapboxMap.addLayer(layer);
-
- assertNotNull(mapboxMap.getLayer("building"));
-
- try {
- layer.setProperties(PropertyFactory.visibility(Property.VISIBLE));
- assertTrue("Never reached as the reference is invalid after adding", false);
- } catch (Exception e) {
- //Expected, reference is no longer valid
- }
+ private class AddRemoveSourceAction implements ViewAction {
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
}
- @Test
- public void testAddRemoveSource() {
- checkViewIsDisplayed(R.id.mapView);
-
- MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
- mapboxMap.addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
- try {
- mapboxMap.removeSource("my-source");
- } catch (NoSuchSourceException e) {
- // it's ok..
- }
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
}
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
+ @Override
+ public void perform(UiController uiController, View view) {
+ MapboxMap mapboxMap = rule.getActivity().getMapboxMap();
+
+ //Add initial source
+ mapboxMap.addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
+
+ //Remove
+ try {
+ mapboxMap.removeSource("my-source");
+ } catch (NoSuchSourceException noSuchSourceException) {
+ fail("Definitively exists: " + noSuchSourceException.getMessage());
+ }
+ assertNull(mapboxMap.getLayer("my-source"));
+
+ //Add
+ Source source = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
+ mapboxMap.addSource(source);
+
+ //Remove, preserving the reference
+ try {
+ mapboxMap.removeSource(source);
+ } catch (NoSuchSourceException noSuchSourceException) {
+ fail("Definitively exists: " + noSuchSourceException.getMessage());
+ }
+
+ //Re-add the reference...
+ mapboxMap.addSource(source);
+
+ //Ensure it's there
+ Assert.assertNotNull(mapboxMap.getSource(source.getId()));
+
+ //Test adding a duplicate source
+ try {
+ Source source2 = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
+ mapboxMap.addSource(source2);
+ fail("Should not have been allowed to add a source with a duplicate id");
+ } catch (CannotAddSourceException cannotAddSourceException) {
+ //OK
+ }
}
+ }
+
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTimingTests.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTimingTests.java
index 0282e1bcd0..57b0fe72ff 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTimingTests.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTimingTests.java
@@ -20,25 +20,26 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class RuntimeStyleTimingTests extends BaseStyleTest {
- @Rule
- public final ActivityTestRule<RuntimeStyleTimingTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTimingTestActivity.class);
-
- private OnMapReadyIdlingResource idlingResource;
-
- @Before
- public void registerIdlingResource() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
-
- @Test
- public void testGetAddRemoveLayer() {
- checkViewIsDisplayed(R.id.mapView);
- //We're good if it didn't crash
- }
-
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTimingTestActivity> rule =
+ new ActivityTestRule<>(RuntimeStyleTimingTestActivity.class);
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ @Before
+ public void registerIdlingResource() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testGetAddRemoveLayer() {
+ checkViewIsDisplayed(R.id.mapView);
+ //We're good if it didn't crash
+ }
+
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerStyleTest.java
index 7132705ca9..5b59d4ceae 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerStyleTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerStyleTest.java
@@ -1,11 +1,10 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.testapp.style;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
@@ -19,1204 +18,1266 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.Property.ICON_ROTATION_ALIGNMENT_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.ICON_TEXT_FIT_NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.ICON_TRANSLATE_ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.SYMBOL_PLACEMENT_POINT;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_ANCHOR_CENTER;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_JUSTIFY_LEFT;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_PITCH_ALIGNMENT_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_ROTATION_ALIGNMENT_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_TRANSFORM_NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_TRANSLATE_ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconHaloBlur;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconHaloColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconHaloWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconKeepUpright;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOffset;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOptional;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconPadding;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconRotate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconRotationAlignment;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconTextFit;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconTextFitPadding;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.symbolAvoidEdges;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.symbolPlacement;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.symbolSpacing;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAllowOverlap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textFont;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textHaloBlur;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textHaloColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textHaloWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textIgnorePlacement;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textJustify;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textKeepUpright;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textLetterSpacing;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textLineHeight;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textMaxAngle;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textMaxWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textOffset;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textOptional;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textPadding;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textPitchAlignment;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textRotate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textRotationAlignment;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textSize;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textTransform;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for SymbolLayer
*/
@RunWith(AndroidJUnit4.class)
public class SymbolLayerStyleTest extends BaseStyleTest {
- private static final String TAG = SymbolLayerStyleTest.class.getSimpleName();
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
- private SymbolLayer layer;
+ private SymbolLayer layer;
- private OnMapReadyIdlingResource idlingResource;
+ private OnMapReadyIdlingResource idlingResource;
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Before
- public void setup() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
- @Test
- public void testSetVisibility() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "visibility");
- assertNotNull(layer);
-
- //Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
-
- //Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
- @Test
- public void testSymbolPlacement() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "symbol-placement");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(symbolPlacement(SYMBOL_PLACEMENT_POINT));
- assertEquals((String) layer.getSymbolPlacement().getValue(), (String) SYMBOL_PLACEMENT_POINT);
- }
+ mapboxMap = rule.getActivity().getMapboxMap();
- @Test
- public void testSymbolSpacing() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "symbol-spacing");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(symbolSpacing(0.3f));
- assertEquals((Float) layer.getSymbolSpacing().getValue(), (Float) 0.3f);
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testSymbolAvoidEdges() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "symbol-avoid-edges");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(symbolAvoidEdges(true));
- assertEquals((Boolean) layer.getSymbolAvoidEdges().getValue(), (Boolean) true);
+ Timber.i("visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testSymbolPlacement() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconAllowOverlap() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-allow-overlap");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconAllowOverlap(true));
- assertEquals((Boolean) layer.getIconAllowOverlap().getValue(), (Boolean) true);
+ Timber.i("symbol-placement");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(symbolPlacement(SYMBOL_PLACEMENT_POINT));
+ assertEquals((String) layer.getSymbolPlacement().getValue(), (String) SYMBOL_PLACEMENT_POINT);
+ }
+
+ @Test
+ public void testSymbolSpacing() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconIgnorePlacement() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-ignore-placement");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconIgnorePlacement(true));
- assertEquals((Boolean) layer.getIconIgnorePlacement().getValue(), (Boolean) true);
+ Timber.i("symbol-spacing");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(symbolSpacing(0.3f));
+ assertEquals((Float) layer.getSymbolSpacing().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testSymbolAvoidEdges() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconOptional() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-optional");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconOptional(true));
- assertEquals((Boolean) layer.getIconOptional().getValue(), (Boolean) true);
+ Timber.i("symbol-avoid-edges");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(symbolAvoidEdges(true));
+ assertEquals((Boolean) layer.getSymbolAvoidEdges().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconAllowOverlap() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconRotationAlignment() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-rotation-alignment");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP));
- assertEquals((String) layer.getIconRotationAlignment().getValue(), (String) ICON_ROTATION_ALIGNMENT_MAP);
+ Timber.i("icon-allow-overlap");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconAllowOverlap(true));
+ assertEquals((Boolean) layer.getIconAllowOverlap().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconIgnorePlacement() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconSize() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-size");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconSize(0.3f));
- assertEquals((Float) layer.getIconSize().getValue(), (Float) 0.3f);
+ Timber.i("icon-ignore-placement");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconIgnorePlacement(true));
+ assertEquals((Boolean) layer.getIconIgnorePlacement().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconOptional() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconTextFit() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-text-fit");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconTextFit(ICON_TEXT_FIT_NONE));
- assertEquals((String) layer.getIconTextFit().getValue(), (String) ICON_TEXT_FIT_NONE);
+ Timber.i("icon-optional");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconOptional(true));
+ assertEquals((Boolean) layer.getIconOptional().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconRotationAlignment() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconTextFitPadding() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-text-fit-padding");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconTextFitPadding(new Float[]{0f,0f,0f,0f}));
- assertEquals((Float[]) layer.getIconTextFitPadding().getValue(), (Float[]) new Float[]{0f,0f,0f,0f});
+ Timber.i("icon-rotation-alignment");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP));
+ assertEquals((String) layer.getIconRotationAlignment().getValue(), (String) ICON_ROTATION_ALIGNMENT_MAP);
+ }
+
+ @Test
+ public void testIconSize() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconImage() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-image");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconImage("undefined"));
- assertEquals((String) layer.getIconImage().getValue(), (String) "undefined");
+ Timber.i("icon-size");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconSize(0.3f));
+ assertEquals((Float) layer.getIconSize().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconTextFit() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconRotate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-rotate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconRotate(0.3f));
- assertEquals((Float) layer.getIconRotate().getValue(), (Float) 0.3f);
+ Timber.i("icon-text-fit");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconTextFit(ICON_TEXT_FIT_NONE));
+ assertEquals((String) layer.getIconTextFit().getValue(), (String) ICON_TEXT_FIT_NONE);
+ }
+
+ @Test
+ public void testIconTextFitPadding() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconPadding() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-padding");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconPadding(0.3f));
- assertEquals((Float) layer.getIconPadding().getValue(), (Float) 0.3f);
+ Timber.i("icon-text-fit-padding");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconTextFitPadding(new Float[] {0f, 0f, 0f, 0f}));
+ assertEquals((Float[]) layer.getIconTextFitPadding().getValue(), (Float[]) new Float[] {0f, 0f, 0f, 0f});
+ }
+
+ @Test
+ public void testIconImage() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconKeepUpright() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-keep-upright");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconKeepUpright(true));
- assertEquals((Boolean) layer.getIconKeepUpright().getValue(), (Boolean) true);
+ Timber.i("icon-image");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconImage("undefined"));
+ assertEquals((String) layer.getIconImage().getValue(), (String) "undefined");
+ }
+
+ @Test
+ public void testIconRotate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconOffset() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-offset");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconOffset(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getIconOffset().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("icon-rotate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconRotate(0.3f));
+ assertEquals((Float) layer.getIconRotate().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconPadding() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextPitchAlignment() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-pitch-alignment");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textPitchAlignment(TEXT_PITCH_ALIGNMENT_MAP));
- assertEquals((String) layer.getTextPitchAlignment().getValue(), (String) TEXT_PITCH_ALIGNMENT_MAP);
+ Timber.i("icon-padding");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconPadding(0.3f));
+ assertEquals((Float) layer.getIconPadding().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconKeepUpright() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextRotationAlignment() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-rotation-alignment");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textRotationAlignment(TEXT_ROTATION_ALIGNMENT_MAP));
- assertEquals((String) layer.getTextRotationAlignment().getValue(), (String) TEXT_ROTATION_ALIGNMENT_MAP);
+ Timber.i("icon-keep-upright");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconKeepUpright(true));
+ assertEquals((Boolean) layer.getIconKeepUpright().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconOffset() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextField() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-field");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textField(""));
- assertEquals((String) layer.getTextField().getValue(), (String) "");
+ Timber.i("icon-offset");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconOffset(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getIconOffset().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testTextPitchAlignment() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextFont() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-font");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textFont(new String[]{"Open Sans Regular", "Arial Unicode MS Regular"}));
- assertEquals((String[]) layer.getTextFont().getValue(), (String[]) new String[]{"Open Sans Regular", "Arial Unicode MS Regular"});
+ Timber.i("text-pitch-alignment");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textPitchAlignment(TEXT_PITCH_ALIGNMENT_MAP));
+ assertEquals((String) layer.getTextPitchAlignment().getValue(), (String) TEXT_PITCH_ALIGNMENT_MAP);
+ }
+
+ @Test
+ public void testTextRotationAlignment() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextSize() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-size");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textSize(0.3f));
- assertEquals((Float) layer.getTextSize().getValue(), (Float) 0.3f);
+ Timber.i("text-rotation-alignment");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textRotationAlignment(TEXT_ROTATION_ALIGNMENT_MAP));
+ assertEquals((String) layer.getTextRotationAlignment().getValue(), (String) TEXT_ROTATION_ALIGNMENT_MAP);
+ }
+
+ @Test
+ public void testTextField() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextMaxWidth() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-max-width");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textMaxWidth(0.3f));
- assertEquals((Float) layer.getTextMaxWidth().getValue(), (Float) 0.3f);
+ Timber.i("text-field");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textField(""));
+ assertEquals((String) layer.getTextField().getValue(), (String) "");
+ }
+
+ @Test
+ public void testTextFont() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextLineHeight() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-line-height");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textLineHeight(0.3f));
- assertEquals((Float) layer.getTextLineHeight().getValue(), (Float) 0.3f);
+ Timber.i("text-font");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textFont(new String[] {"Open Sans Regular", "Arial Unicode MS Regular"}));
+ assertEquals((String[]) layer.getTextFont().getValue(), (String[]) new String[] {"Open Sans Regular",
+ "Arial Unicode MS Regular"});
+ }
+
+ @Test
+ public void testTextSize() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextLetterSpacing() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-letter-spacing");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textLetterSpacing(0.3f));
- assertEquals((Float) layer.getTextLetterSpacing().getValue(), (Float) 0.3f);
+ Timber.i("text-size");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textSize(0.3f));
+ assertEquals((Float) layer.getTextSize().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextMaxWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextJustify() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-justify");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textJustify(TEXT_JUSTIFY_LEFT));
- assertEquals((String) layer.getTextJustify().getValue(), (String) TEXT_JUSTIFY_LEFT);
+ Timber.i("text-max-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textMaxWidth(0.3f));
+ assertEquals((Float) layer.getTextMaxWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextLineHeight() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextAnchor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-anchor");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textAnchor(TEXT_ANCHOR_CENTER));
- assertEquals((String) layer.getTextAnchor().getValue(), (String) TEXT_ANCHOR_CENTER);
+ Timber.i("text-line-height");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textLineHeight(0.3f));
+ assertEquals((Float) layer.getTextLineHeight().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextLetterSpacing() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextMaxAngle() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-max-angle");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textMaxAngle(0.3f));
- assertEquals((Float) layer.getTextMaxAngle().getValue(), (Float) 0.3f);
+ Timber.i("text-letter-spacing");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textLetterSpacing(0.3f));
+ assertEquals((Float) layer.getTextLetterSpacing().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextJustify() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextRotate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-rotate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textRotate(0.3f));
- assertEquals((Float) layer.getTextRotate().getValue(), (Float) 0.3f);
+ Timber.i("text-justify");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textJustify(TEXT_JUSTIFY_LEFT));
+ assertEquals((String) layer.getTextJustify().getValue(), (String) TEXT_JUSTIFY_LEFT);
+ }
+
+ @Test
+ public void testTextAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextPadding() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-padding");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textPadding(0.3f));
- assertEquals((Float) layer.getTextPadding().getValue(), (Float) 0.3f);
+ Timber.i("text-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textAnchor(TEXT_ANCHOR_CENTER));
+ assertEquals((String) layer.getTextAnchor().getValue(), (String) TEXT_ANCHOR_CENTER);
+ }
+
+ @Test
+ public void testTextMaxAngle() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextKeepUpright() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-keep-upright");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textKeepUpright(true));
- assertEquals((Boolean) layer.getTextKeepUpright().getValue(), (Boolean) true);
+ Timber.i("text-max-angle");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textMaxAngle(0.3f));
+ assertEquals((Float) layer.getTextMaxAngle().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextRotate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextTransform() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-transform");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textTransform(TEXT_TRANSFORM_NONE));
- assertEquals((String) layer.getTextTransform().getValue(), (String) TEXT_TRANSFORM_NONE);
+ Timber.i("text-rotate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textRotate(0.3f));
+ assertEquals((Float) layer.getTextRotate().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextPadding() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextOffset() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-offset");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textOffset(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getTextOffset().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("text-padding");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textPadding(0.3f));
+ assertEquals((Float) layer.getTextPadding().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextKeepUpright() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextAllowOverlap() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-allow-overlap");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textAllowOverlap(true));
- assertEquals((Boolean) layer.getTextAllowOverlap().getValue(), (Boolean) true);
+ Timber.i("text-keep-upright");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textKeepUpright(true));
+ assertEquals((Boolean) layer.getTextKeepUpright().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testTextTransform() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextIgnorePlacement() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-ignore-placement");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textIgnorePlacement(true));
- assertEquals((Boolean) layer.getTextIgnorePlacement().getValue(), (Boolean) true);
+ Timber.i("text-transform");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textTransform(TEXT_TRANSFORM_NONE));
+ assertEquals((String) layer.getTextTransform().getValue(), (String) TEXT_TRANSFORM_NONE);
+ }
+
+ @Test
+ public void testTextOffset() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextOptional() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-optional");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textOptional(true));
- assertEquals((Boolean) layer.getTextOptional().getValue(), (Boolean) true);
+ Timber.i("text-offset");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textOffset(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getTextOffset().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testTextAllowOverlap() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconOpacity() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-opacity");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconOpacity(0.3f));
- assertEquals((Float) layer.getIconOpacity().getValue(), (Float) 0.3f);
+ Timber.i("text-allow-overlap");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textAllowOverlap(true));
+ assertEquals((Boolean) layer.getTextAllowOverlap().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testTextIgnorePlacement() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getIconColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("text-ignore-placement");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textIgnorePlacement(true));
+ assertEquals((Boolean) layer.getTextIgnorePlacement().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testTextOptional() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconColor(Color.RED));
- assertEquals(layer.getIconColorAsInt(), Color.RED);
+ Timber.i("text-optional");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textOptional(true));
+ assertEquals((Boolean) layer.getTextOptional().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconHaloColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-halo-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconHaloColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getIconHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("icon-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconOpacity(0.3f));
+ assertEquals((Float) layer.getIconOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconHaloColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-halo-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconHaloColor(Color.RED));
- assertEquals(layer.getIconHaloColorAsInt(), Color.RED);
+ Timber.i("icon-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getIconColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testIconColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconHaloWidth() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-halo-width");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconHaloWidth(0.3f));
- assertEquals((Float) layer.getIconHaloWidth().getValue(), (Float) 0.3f);
+ Timber.i("icon-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconColor(Color.RED));
+ assertEquals(layer.getIconColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testIconHaloColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconHaloBlur() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-halo-blur");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconHaloBlur(0.3f));
- assertEquals((Float) layer.getIconHaloBlur().getValue(), (Float) 0.3f);
+ Timber.i("icon-halo-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconHaloColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getIconHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testIconHaloColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconTranslate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-translate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconTranslate(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getIconTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("icon-halo-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconHaloColor(Color.RED));
+ assertEquals(layer.getIconHaloColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testIconHaloWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconTranslateAnchor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-translate-anchor");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconTranslateAnchor(ICON_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getIconTranslateAnchor().getValue(), (String) ICON_TRANSLATE_ANCHOR_MAP);
+ Timber.i("icon-halo-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconHaloWidth(0.3f));
+ assertEquals((Float) layer.getIconHaloWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconHaloBlur() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextOpacity() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-opacity");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textOpacity(0.3f));
- assertEquals((Float) layer.getTextOpacity().getValue(), (Float) 0.3f);
+ Timber.i("icon-halo-blur");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconHaloBlur(0.3f));
+ assertEquals((Float) layer.getIconHaloBlur().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getTextColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("icon-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getIconTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testIconTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textColor(Color.RED));
- assertEquals(layer.getTextColorAsInt(), Color.RED);
+ Timber.i("icon-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconTranslateAnchor(ICON_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getIconTranslateAnchor().getValue(), (String) ICON_TRANSLATE_ANCHOR_MAP);
+ }
+
+ @Test
+ public void testTextOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextHaloColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-halo-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textHaloColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getTextHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("text-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textOpacity(0.3f));
+ assertEquals((Float) layer.getTextOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextHaloColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-halo-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textHaloColor(Color.RED));
- assertEquals(layer.getTextHaloColorAsInt(), Color.RED);
+ Timber.i("text-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getTextColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testTextColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextHaloWidth() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-halo-width");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textHaloWidth(0.3f));
- assertEquals((Float) layer.getTextHaloWidth().getValue(), (Float) 0.3f);
+ Timber.i("text-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textColor(Color.RED));
+ assertEquals(layer.getTextColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testTextHaloColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextHaloBlur() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-halo-blur");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textHaloBlur(0.3f));
- assertEquals((Float) layer.getTextHaloBlur().getValue(), (Float) 0.3f);
+ Timber.i("text-halo-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textHaloColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getTextHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testTextHaloColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextTranslate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-translate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textTranslate(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getTextTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("text-halo-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textHaloColor(Color.RED));
+ assertEquals(layer.getTextHaloColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testTextHaloWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextTranslateAnchor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-translate-anchor");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textTranslateAnchor(TEXT_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getTextTranslateAnchor().getValue(), (String) TEXT_TRANSLATE_ANCHOR_MAP);
+ Timber.i("text-halo-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textHaloWidth(0.3f));
+ assertEquals((Float) layer.getTextHaloWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextHaloBlur() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
+ Timber.i("text-halo-blur");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textHaloBlur(0.3f));
+ assertEquals((Float) layer.getTextHaloBlur().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("text-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getTextTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testTextTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("text-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textTranslateAnchor(TEXT_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getTextTranslateAnchor().getValue(), (String) TEXT_TRANSLATE_ANCHOR_MAP);
+ }
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
index 5bc3f597c1..f4c50a2ffb 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
@@ -1,11 +1,10 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.testapp.style;
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
@@ -19,1204 +18,1266 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.Property.ICON_ROTATION_ALIGNMENT_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.ICON_TEXT_FIT_NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.ICON_TRANSLATE_ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.SYMBOL_PLACEMENT_POINT;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_ANCHOR_CENTER;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_JUSTIFY_LEFT;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_PITCH_ALIGNMENT_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_ROTATION_ALIGNMENT_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_TRANSFORM_NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_TRANSLATE_ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconHaloBlur;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconHaloColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconHaloWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconKeepUpright;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOffset;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOptional;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconPadding;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconRotate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconRotationAlignment;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconTextFit;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconTextFitPadding;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.symbolAvoidEdges;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.symbolPlacement;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.symbolSpacing;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAllowOverlap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textFont;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textHaloBlur;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textHaloColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textHaloWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textIgnorePlacement;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textJustify;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textKeepUpright;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textLetterSpacing;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textLineHeight;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textMaxAngle;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textMaxWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textOffset;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textOptional;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textPadding;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textPitchAlignment;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textRotate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textRotationAlignment;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textSize;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textTransform;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for SymbolLayer
*/
@RunWith(AndroidJUnit4.class)
public class SymbolLayerTest extends BaseStyleTest {
- private static final String TAG = SymbolLayerTest.class.getSimpleName();
- @Rule
- public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
- private SymbolLayer layer;
+ private SymbolLayer layer;
- private OnMapReadyIdlingResource idlingResource;
+ private OnMapReadyIdlingResource idlingResource;
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Before
- public void setup() {
- idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
- Espresso.registerIdlingResources(idlingResource);
- }
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
- @Test
- public void testSetVisibility() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "visibility");
- assertNotNull(layer);
-
- //Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
-
- //Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
- @Test
- public void testSymbolPlacement() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "symbol-placement");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(symbolPlacement(SYMBOL_PLACEMENT_POINT));
- assertEquals((String) layer.getSymbolPlacement().getValue(), (String) SYMBOL_PLACEMENT_POINT);
- }
+ mapboxMap = rule.getActivity().getMapboxMap();
- @Test
- public void testSymbolSpacing() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "symbol-spacing");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(symbolSpacing(0.3f));
- assertEquals((Float) layer.getSymbolSpacing().getValue(), (Float) 0.3f);
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testSymbolAvoidEdges() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "symbol-avoid-edges");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(symbolAvoidEdges(true));
- assertEquals((Boolean) layer.getSymbolAvoidEdges().getValue(), (Boolean) true);
+ Timber.i("visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testSymbolPlacement() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconAllowOverlap() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-allow-overlap");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconAllowOverlap(true));
- assertEquals((Boolean) layer.getIconAllowOverlap().getValue(), (Boolean) true);
+ Timber.i("symbol-placement");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(symbolPlacement(SYMBOL_PLACEMENT_POINT));
+ assertEquals((String) layer.getSymbolPlacement().getValue(), (String) SYMBOL_PLACEMENT_POINT);
+ }
+
+ @Test
+ public void testSymbolSpacing() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconIgnorePlacement() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-ignore-placement");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconIgnorePlacement(true));
- assertEquals((Boolean) layer.getIconIgnorePlacement().getValue(), (Boolean) true);
+ Timber.i("symbol-spacing");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(symbolSpacing(0.3f));
+ assertEquals((Float) layer.getSymbolSpacing().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testSymbolAvoidEdges() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconOptional() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-optional");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconOptional(true));
- assertEquals((Boolean) layer.getIconOptional().getValue(), (Boolean) true);
+ Timber.i("symbol-avoid-edges");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(symbolAvoidEdges(true));
+ assertEquals((Boolean) layer.getSymbolAvoidEdges().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconAllowOverlap() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconRotationAlignment() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-rotation-alignment");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP));
- assertEquals((String) layer.getIconRotationAlignment().getValue(), (String) ICON_ROTATION_ALIGNMENT_MAP);
+ Timber.i("icon-allow-overlap");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconAllowOverlap(true));
+ assertEquals((Boolean) layer.getIconAllowOverlap().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconIgnorePlacement() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconSize() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-size");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconSize(0.3f));
- assertEquals((Float) layer.getIconSize().getValue(), (Float) 0.3f);
+ Timber.i("icon-ignore-placement");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconIgnorePlacement(true));
+ assertEquals((Boolean) layer.getIconIgnorePlacement().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconOptional() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconTextFit() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-text-fit");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconTextFit(ICON_TEXT_FIT_NONE));
- assertEquals((String) layer.getIconTextFit().getValue(), (String) ICON_TEXT_FIT_NONE);
+ Timber.i("icon-optional");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconOptional(true));
+ assertEquals((Boolean) layer.getIconOptional().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconRotationAlignment() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconTextFitPadding() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-text-fit-padding");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconTextFitPadding(new Float[]{0f,0f,0f,0f}));
- assertEquals((Float[]) layer.getIconTextFitPadding().getValue(), (Float[]) new Float[]{0f,0f,0f,0f});
+ Timber.i("icon-rotation-alignment");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP));
+ assertEquals((String) layer.getIconRotationAlignment().getValue(), (String) ICON_ROTATION_ALIGNMENT_MAP);
+ }
+
+ @Test
+ public void testIconSize() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconImage() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-image");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconImage("undefined"));
- assertEquals((String) layer.getIconImage().getValue(), (String) "undefined");
+ Timber.i("icon-size");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconSize(0.3f));
+ assertEquals((Float) layer.getIconSize().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconTextFit() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconRotate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-rotate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconRotate(0.3f));
- assertEquals((Float) layer.getIconRotate().getValue(), (Float) 0.3f);
+ Timber.i("icon-text-fit");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconTextFit(ICON_TEXT_FIT_NONE));
+ assertEquals((String) layer.getIconTextFit().getValue(), (String) ICON_TEXT_FIT_NONE);
+ }
+
+ @Test
+ public void testIconTextFitPadding() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconPadding() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-padding");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconPadding(0.3f));
- assertEquals((Float) layer.getIconPadding().getValue(), (Float) 0.3f);
+ Timber.i("icon-text-fit-padding");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconTextFitPadding(new Float[] {0f, 0f, 0f, 0f}));
+ assertEquals((Float[]) layer.getIconTextFitPadding().getValue(), (Float[]) new Float[] {0f, 0f, 0f, 0f});
+ }
+
+ @Test
+ public void testIconImage() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconKeepUpright() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-keep-upright");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconKeepUpright(true));
- assertEquals((Boolean) layer.getIconKeepUpright().getValue(), (Boolean) true);
+ Timber.i("icon-image");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconImage("undefined"));
+ assertEquals((String) layer.getIconImage().getValue(), (String) "undefined");
+ }
+
+ @Test
+ public void testIconRotate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconOffset() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-offset");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconOffset(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getIconOffset().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("icon-rotate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconRotate(0.3f));
+ assertEquals((Float) layer.getIconRotate().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconPadding() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextPitchAlignment() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-pitch-alignment");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textPitchAlignment(TEXT_PITCH_ALIGNMENT_MAP));
- assertEquals((String) layer.getTextPitchAlignment().getValue(), (String) TEXT_PITCH_ALIGNMENT_MAP);
+ Timber.i("icon-padding");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconPadding(0.3f));
+ assertEquals((Float) layer.getIconPadding().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconKeepUpright() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextRotationAlignment() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-rotation-alignment");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textRotationAlignment(TEXT_ROTATION_ALIGNMENT_MAP));
- assertEquals((String) layer.getTextRotationAlignment().getValue(), (String) TEXT_ROTATION_ALIGNMENT_MAP);
+ Timber.i("icon-keep-upright");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconKeepUpright(true));
+ assertEquals((Boolean) layer.getIconKeepUpright().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconOffset() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextField() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-field");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textField(""));
- assertEquals((String) layer.getTextField().getValue(), (String) "");
+ Timber.i("icon-offset");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconOffset(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getIconOffset().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testTextPitchAlignment() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextFont() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-font");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textFont(new String[]{"Open Sans Regular", "Arial Unicode MS Regular"}));
- assertEquals((String[]) layer.getTextFont().getValue(), (String[]) new String[]{"Open Sans Regular", "Arial Unicode MS Regular"});
+ Timber.i("text-pitch-alignment");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textPitchAlignment(TEXT_PITCH_ALIGNMENT_MAP));
+ assertEquals((String) layer.getTextPitchAlignment().getValue(), (String) TEXT_PITCH_ALIGNMENT_MAP);
+ }
+
+ @Test
+ public void testTextRotationAlignment() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextSize() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-size");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textSize(0.3f));
- assertEquals((Float) layer.getTextSize().getValue(), (Float) 0.3f);
+ Timber.i("text-rotation-alignment");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textRotationAlignment(TEXT_ROTATION_ALIGNMENT_MAP));
+ assertEquals((String) layer.getTextRotationAlignment().getValue(), (String) TEXT_ROTATION_ALIGNMENT_MAP);
+ }
+
+ @Test
+ public void testTextField() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextMaxWidth() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-max-width");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textMaxWidth(0.3f));
- assertEquals((Float) layer.getTextMaxWidth().getValue(), (Float) 0.3f);
+ Timber.i("text-field");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textField(""));
+ assertEquals((String) layer.getTextField().getValue(), (String) "");
+ }
+
+ @Test
+ public void testTextFont() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextLineHeight() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-line-height");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textLineHeight(0.3f));
- assertEquals((Float) layer.getTextLineHeight().getValue(), (Float) 0.3f);
+ Timber.i("text-font");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textFont(new String[] {"Open Sans Regular", "Arial Unicode MS Regular"}));
+ assertEquals((String[]) layer.getTextFont().getValue(), (String[]) new String[] {"Open Sans Regular",
+ "Arial Unicode MS Regular"});
+ }
+
+ @Test
+ public void testTextSize() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextLetterSpacing() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-letter-spacing");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textLetterSpacing(0.3f));
- assertEquals((Float) layer.getTextLetterSpacing().getValue(), (Float) 0.3f);
+ Timber.i("text-size");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textSize(0.3f));
+ assertEquals((Float) layer.getTextSize().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextMaxWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextJustify() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-justify");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textJustify(TEXT_JUSTIFY_LEFT));
- assertEquals((String) layer.getTextJustify().getValue(), (String) TEXT_JUSTIFY_LEFT);
+ Timber.i("text-max-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textMaxWidth(0.3f));
+ assertEquals((Float) layer.getTextMaxWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextLineHeight() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextAnchor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-anchor");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textAnchor(TEXT_ANCHOR_CENTER));
- assertEquals((String) layer.getTextAnchor().getValue(), (String) TEXT_ANCHOR_CENTER);
+ Timber.i("text-line-height");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textLineHeight(0.3f));
+ assertEquals((Float) layer.getTextLineHeight().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextLetterSpacing() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextMaxAngle() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-max-angle");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textMaxAngle(0.3f));
- assertEquals((Float) layer.getTextMaxAngle().getValue(), (Float) 0.3f);
+ Timber.i("text-letter-spacing");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textLetterSpacing(0.3f));
+ assertEquals((Float) layer.getTextLetterSpacing().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextJustify() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextRotate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-rotate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textRotate(0.3f));
- assertEquals((Float) layer.getTextRotate().getValue(), (Float) 0.3f);
+ Timber.i("text-justify");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textJustify(TEXT_JUSTIFY_LEFT));
+ assertEquals((String) layer.getTextJustify().getValue(), (String) TEXT_JUSTIFY_LEFT);
+ }
+
+ @Test
+ public void testTextAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextPadding() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-padding");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textPadding(0.3f));
- assertEquals((Float) layer.getTextPadding().getValue(), (Float) 0.3f);
+ Timber.i("text-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textAnchor(TEXT_ANCHOR_CENTER));
+ assertEquals((String) layer.getTextAnchor().getValue(), (String) TEXT_ANCHOR_CENTER);
+ }
+
+ @Test
+ public void testTextMaxAngle() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextKeepUpright() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-keep-upright");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textKeepUpright(true));
- assertEquals((Boolean) layer.getTextKeepUpright().getValue(), (Boolean) true);
+ Timber.i("text-max-angle");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textMaxAngle(0.3f));
+ assertEquals((Float) layer.getTextMaxAngle().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextRotate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextTransform() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-transform");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textTransform(TEXT_TRANSFORM_NONE));
- assertEquals((String) layer.getTextTransform().getValue(), (String) TEXT_TRANSFORM_NONE);
+ Timber.i("text-rotate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textRotate(0.3f));
+ assertEquals((Float) layer.getTextRotate().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextPadding() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextOffset() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-offset");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textOffset(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getTextOffset().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("text-padding");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textPadding(0.3f));
+ assertEquals((Float) layer.getTextPadding().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextKeepUpright() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextAllowOverlap() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-allow-overlap");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textAllowOverlap(true));
- assertEquals((Boolean) layer.getTextAllowOverlap().getValue(), (Boolean) true);
+ Timber.i("text-keep-upright");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textKeepUpright(true));
+ assertEquals((Boolean) layer.getTextKeepUpright().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testTextTransform() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextIgnorePlacement() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-ignore-placement");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textIgnorePlacement(true));
- assertEquals((Boolean) layer.getTextIgnorePlacement().getValue(), (Boolean) true);
+ Timber.i("text-transform");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textTransform(TEXT_TRANSFORM_NONE));
+ assertEquals((String) layer.getTextTransform().getValue(), (String) TEXT_TRANSFORM_NONE);
+ }
+
+ @Test
+ public void testTextOffset() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextOptional() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-optional");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textOptional(true));
- assertEquals((Boolean) layer.getTextOptional().getValue(), (Boolean) true);
+ Timber.i("text-offset");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textOffset(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getTextOffset().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testTextAllowOverlap() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconOpacity() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-opacity");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconOpacity(0.3f));
- assertEquals((Float) layer.getIconOpacity().getValue(), (Float) 0.3f);
+ Timber.i("text-allow-overlap");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textAllowOverlap(true));
+ assertEquals((Boolean) layer.getTextAllowOverlap().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testTextIgnorePlacement() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getIconColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("text-ignore-placement");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textIgnorePlacement(true));
+ assertEquals((Boolean) layer.getTextIgnorePlacement().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testTextOptional() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconColor(Color.RED));
- assertEquals(layer.getIconColorAsInt(), Color.RED);
+ Timber.i("text-optional");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textOptional(true));
+ assertEquals((Boolean) layer.getTextOptional().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconHaloColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-halo-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconHaloColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getIconHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("icon-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconOpacity(0.3f));
+ assertEquals((Float) layer.getIconOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconHaloColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-halo-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconHaloColor(Color.RED));
- assertEquals(layer.getIconHaloColorAsInt(), Color.RED);
+ Timber.i("icon-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getIconColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testIconColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconHaloWidth() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-halo-width");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconHaloWidth(0.3f));
- assertEquals((Float) layer.getIconHaloWidth().getValue(), (Float) 0.3f);
+ Timber.i("icon-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconColor(Color.RED));
+ assertEquals(layer.getIconColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testIconHaloColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconHaloBlur() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-halo-blur");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconHaloBlur(0.3f));
- assertEquals((Float) layer.getIconHaloBlur().getValue(), (Float) 0.3f);
+ Timber.i("icon-halo-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconHaloColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getIconHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testIconHaloColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconTranslate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-translate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconTranslate(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getIconTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("icon-halo-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconHaloColor(Color.RED));
+ assertEquals(layer.getIconHaloColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testIconHaloWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testIconTranslateAnchor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "icon-translate-anchor");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(iconTranslateAnchor(ICON_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getIconTranslateAnchor().getValue(), (String) ICON_TRANSLATE_ANCHOR_MAP);
+ Timber.i("icon-halo-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconHaloWidth(0.3f));
+ assertEquals((Float) layer.getIconHaloWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconHaloBlur() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextOpacity() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-opacity");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textOpacity(0.3f));
- assertEquals((Float) layer.getTextOpacity().getValue(), (Float) 0.3f);
+ Timber.i("icon-halo-blur");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconHaloBlur(0.3f));
+ assertEquals((Float) layer.getIconHaloBlur().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getTextColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("icon-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getIconTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testIconTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textColor(Color.RED));
- assertEquals(layer.getTextColorAsInt(), Color.RED);
+ Timber.i("icon-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconTranslateAnchor(ICON_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getIconTranslateAnchor().getValue(), (String) ICON_TRANSLATE_ANCHOR_MAP);
+ }
+
+ @Test
+ public void testTextOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextHaloColor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-halo-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textHaloColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getTextHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ Timber.i("text-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textOpacity(0.3f));
+ assertEquals((Float) layer.getTextOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextHaloColorAsInt() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-halo-color");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textHaloColor(Color.RED));
- assertEquals(layer.getTextHaloColorAsInt(), Color.RED);
+ Timber.i("text-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getTextColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testTextColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextHaloWidth() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-halo-width");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textHaloWidth(0.3f));
- assertEquals((Float) layer.getTextHaloWidth().getValue(), (Float) 0.3f);
+ Timber.i("text-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textColor(Color.RED));
+ assertEquals(layer.getTextColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testTextHaloColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextHaloBlur() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-halo-blur");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textHaloBlur(0.3f));
- assertEquals((Float) layer.getTextHaloBlur().getValue(), (Float) 0.3f);
+ Timber.i("text-halo-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textHaloColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getTextHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testTextHaloColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextTranslate() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-translate");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textTranslate(new Float[]{0f,0f}));
- assertEquals((Float[]) layer.getTextTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ Timber.i("text-halo-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textHaloColor(Color.RED));
+ assertEquals(layer.getTextHaloColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testTextHaloWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
-
- @Test
- public void testTextTranslateAnchor() {
- checkViewIsDisplayed(R.id.mapView);
-
- mapboxMap = rule.getActivity().getMapboxMap();
-
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- //Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
- Log.i(TAG, "text-translate-anchor");
- assertNotNull(layer);
-
- //Set and Get
- layer.setProperties(textTranslateAnchor(TEXT_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getTextTranslateAnchor().getValue(), (String) TEXT_TRANSLATE_ANCHOR_MAP);
+ Timber.i("text-halo-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textHaloWidth(0.3f));
+ assertEquals((Float) layer.getTextHaloWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextHaloBlur() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
+ Timber.i("text-halo-blur");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textHaloBlur(0.3f));
+ assertEquals((Float) layer.getTextHaloBlur().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("text-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getTextTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
+ }
+
+ @Test
+ public void testTextTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ //Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
+ }
+ Timber.i("text-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textTranslateAnchor(TEXT_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getTextTranslateAnchor().getValue(), (String) TEXT_TRANSLATE_ANCHOR_MAP);
+ }
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs
index bc0d22bb25..3b81b0805b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs
@@ -2,14 +2,14 @@
const type = locals.type;
const properties = locals.properties;
-%>
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
+import timber.log.Timber;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.<%- camelize(type) %>Layer;
@@ -32,7 +32,6 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
*/
@RunWith(AndroidJUnit4.class)
public class <%- camelize(type) %>LayerTest extends BaseStyleTest {
- private static final String TAG = <%- camelize(type) %>LayerTest.class.getSimpleName();
@Rule
public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
@@ -56,11 +55,11 @@ public class <%- camelize(type) %>LayerTest extends BaseStyleTest {
mapboxMap = rule.getActivity().getMapboxMap();
<% if (type === 'background') { -%>
- Log.i(TAG, "Retrieving layer");
+ Timber.i("Retrieving layer");
layer = mapboxMap.getLayerAs("background");
<% } else { -%>
if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
+ Timber.i("Adding layer");
layer = new <%- camelize(type) %>Layer("my-layer", "composite");
layer.setSourceLayer("composite");
mapboxMap.addLayer(layer);
@@ -68,7 +67,7 @@ public class <%- camelize(type) %>LayerTest extends BaseStyleTest {
layer = mapboxMap.getLayerAs("my-layer");
}
<% } -%>
- Log.i(TAG, "visibility");
+ Timber.i("visibility");
assertNotNull(layer);
//Get initial
@@ -87,11 +86,11 @@ public class <%- camelize(type) %>LayerTest extends BaseStyleTest {
mapboxMap = rule.getActivity().getMapboxMap();
<% if (type === 'background') { -%>
- Log.i(TAG, "Retrieving layer");
+ Timber.i("Retrieving layer");
layer = mapboxMap.getLayerAs("background");
<% } else { -%>
if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
+ Timber.i("Adding layer");
layer = new <%- camelize(type) %>Layer("my-layer", "composite");
layer.setSourceLayer("composite");
mapboxMap.addLayer(layer);
@@ -99,7 +98,7 @@ public class <%- camelize(type) %>LayerTest extends BaseStyleTest {
layer = mapboxMap.getLayerAs("my-layer");
}
<% } -%>
- Log.i(TAG, "<%- property.name %>");
+ Timber.i("<%- property.name %>");
assertNotNull(layer);
//Set and Get
@@ -115,11 +114,11 @@ public class <%- camelize(type) %>LayerTest extends BaseStyleTest {
mapboxMap = rule.getActivity().getMapboxMap();
<% if (type === 'background') { -%>
- Log.i(TAG, "Retrieving layer");
+ Timber.i("Retrieving layer");
layer = mapboxMap.getLayerAs("background");
<% } else { -%>
if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Log.i(TAG, "Adding layer");
+ Timber.i("Adding layer");
layer = new <%- camelize(type) %>Layer("my-layer", "composite");
layer.setSourceLayer("composite");
mapboxMap.addLayer(layer);
@@ -127,7 +126,7 @@ public class <%- camelize(type) %>LayerTest extends BaseStyleTest {
layer = mapboxMap.getLayerAs("my-layer");
}
<% } -%>
- Log.i(TAG, "<%- property.name %>");
+ Timber.i("<%- property.name %>");
assertNotNull(layer);
//Set and Get
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/DrawerUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/DrawerUtils.java
index 8d8905fdf4..d9ced47369 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/DrawerUtils.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/DrawerUtils.java
@@ -15,15 +15,15 @@ import static android.support.test.espresso.matcher.ViewMatchers.withContentDesc
public class DrawerUtils {
- private final static String HOME_BUTTON_STRING = "Navigate up";
+ private static final String HOME_BUTTON_STRING = "Navigate up";
- public static void openDrawer(){
- onView(withContentDescription(HOME_BUTTON_STRING)).perform(click());
- }
+ public static void openDrawer() {
+ onView(withContentDescription(HOME_BUTTON_STRING)).perform(click());
+ }
- public static void clickItem(@StringRes int txtId){
- Espresso.onView(Matchers.allOf(ViewMatchers.withId(R.id.design_menu_item_text),
- ViewMatchers.hasSibling(ViewMatchers.withText(txtId)))).perform(ViewActions.click());
- }
+ public static void clickItem(@StringRes int txtId) {
+ Espresso.onView(Matchers.allOf(ViewMatchers.withId(R.id.design_menu_item_text),
+ ViewMatchers.hasSibling(ViewMatchers.withText(txtId)))).perform(ViewActions.click());
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/GestureUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/GestureUtils.java
index 114fbc549e..3376f5eda4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/GestureUtils.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/GestureUtils.java
@@ -8,8 +8,8 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId;
public class GestureUtils {
- public static void doubleClickGesture(@IdRes int id){
- onView(withId(id)).perform(doubleClick());
- }
+ public static void doubleClickGesture(@IdRes int id) {
+ onView(withId(id)).perform(doubleClick());
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java
index c966f61f8c..6e582c6a3a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java
@@ -2,56 +2,56 @@ package com.mapbox.mapboxsdk.testapp.utils;
import android.app.Activity;
import android.support.test.espresso.IdlingResource;
-import android.util.Log;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import timber.log.Timber;
+
import com.mapbox.mapboxsdk.maps.MapboxMap;
import java.lang.reflect.Field;
public class OnMapReadyIdlingResource implements IdlingResource {
- private final Activity activity;
- private MapboxMap mapboxMap;
- private IdlingResource.ResourceCallback resourceCallback;
+ private final Activity activity;
+ private MapboxMap mapboxMap;
+ private IdlingResource.ResourceCallback resourceCallback;
- public OnMapReadyIdlingResource(Activity activity) {
- this.activity = activity;
- }
+ public OnMapReadyIdlingResource(Activity activity) {
+ this.activity = activity;
+ }
- @Override
- public String getName() {
- return getClass().getSimpleName();
- }
+ @Override
+ public String getName() {
+ return getClass().getSimpleName();
+ }
- @Override
- public boolean isIdleNow() {
- boolean idle = isMapboxMapReady();
- if (idle && resourceCallback != null) {
- resourceCallback.onTransitionToIdle();
- }
- return idle;
+ @Override
+ public boolean isIdleNow() {
+ boolean idle = isMapboxMapReady();
+ if (idle && resourceCallback != null) {
+ resourceCallback.onTransitionToIdle();
}
-
- @Override
- public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
- this.resourceCallback = resourceCallback;
+ return idle;
+ }
+
+ @Override
+ public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
+ this.resourceCallback = resourceCallback;
+ }
+
+ private boolean isMapboxMapReady() {
+ try {
+ Field field = activity.getClass().getDeclaredField("mapboxMap");
+ field.setAccessible(true);
+ mapboxMap = (MapboxMap) field.get(activity);
+ Timber.e("isMapboxReady called with value " + (mapboxMap != null));
+ return mapboxMap != null;
+ } catch (Exception exception) {
+ Timber.e("could not reflect", exception);
+ return false;
}
+ }
- private boolean isMapboxMapReady() {
- try {
- Field field = activity.getClass().getDeclaredField("mapboxMap");
- field.setAccessible(true);
- mapboxMap = (MapboxMap) field.get(activity);
- Log.e(MapboxConstants.TAG, "isMapboxReady called with value " + (mapboxMap != null));
- return mapboxMap != null;
- } catch (Exception e) {
- Log.e(MapboxConstants.TAG, "could not reflect", e);
- return false;
- }
- }
-
- public MapboxMap getMapboxMap() {
- return mapboxMap;
- }
+ public MapboxMap getMapboxMap() {
+ return mapboxMap;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ScreenshotUtil.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ScreenshotUtil.java
index 8fedf38619..77bfc519bf 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ScreenshotUtil.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ScreenshotUtil.java
@@ -4,7 +4,9 @@ import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.os.Environment;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
@@ -23,114 +25,113 @@ import java.util.UUID;
*/
public class ScreenshotUtil {
- private static final String LOG_TAG = ScreenshotUtil.class.getName();
+ // Where to store the files. This path is required by AWS Device Farm:
+ // http://docs.aws.amazon.com/devicefarm/latest/developerguide/test-types-android-instrumentation.html
+ // #test-types-android-instrumentation-screenshots
+ private static final String SCREENSHOT_FOLDER = "test-screenshots";
- // Where to store the files. This path is required by AWS Device Farm:
- // http://docs.aws.amazon.com/devicefarm/latest/developerguide/test-types-android-instrumentation.html#test-types-android-instrumentation-screenshots
- private static final String SCREENSHOT_FOLDER = "test-screenshots";
+ // Image type and quality
+ private static final String DEFAULT_IMAGE_EXTENSION = ".png";
+ private static final Bitmap.CompressFormat DEFAULT_IMAGE_FORMAT = Bitmap.CompressFormat.PNG;
+ private static final int DEFAULT_IMAGE_QUALITY = 100;
- // Image type and quality
- private static final String DEFAULT_IMAGE_EXTENSION = ".png";
- private static final Bitmap.CompressFormat DEFAULT_IMAGE_FORMAT = Bitmap.CompressFormat.PNG;
- private static final int DEFAULT_IMAGE_QUALITY = 100;
+ public static void take(Activity activity, String testName) {
- public static void take(Activity activity, String testName) {
-
- // Check if storage is available
- if (!isExternalStorageWritable()) {
- Log.d(LOG_TAG, "External storage is not available.");
- return;
- }
+ // Check if storage is available
+ if (!isExternalStorageWritable()) {
+ Timber.d("External storage is not available.");
+ return;
+ }
- // Get a bitmap from the activity root view. When the drawing cache is enabled,
-// // the next call to getDrawingCache() will draw the view in a bitmap.
- View rootView = activity.getWindow().getDecorView().getRootView();
-// rootView.setDrawingCacheEnabled(true);r
-// rootView.setDrawingCacheEnabled(false);
-
- Bitmap bitmap = null;
-
- // Add the SurfaceView bit (see getAllTextureViews() below)
- List<TextureView> tilingViews = getAllTextureViews(rootView);
- if (tilingViews.size() > 0) {
- bitmap = Bitmap.createBitmap(tilingViews.get(0).getHeight(),tilingViews.get(0).getWidth(), Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- for (TextureView TextureView : tilingViews) {
- Bitmap b = TextureView.getBitmap(TextureView.getWidth(), TextureView.getHeight());
- int[] location = new int[2];
- TextureView.getLocationInWindow(location);
- int[] location2 = new int[2];
- TextureView.getLocationOnScreen(location2);
- canvas.drawBitmap(b, 0,0, null);
- }
- }
+ // Get a bitmap from the activity root view. When the drawing cache is enabled,
+ // the next call to getDrawingCache() will draw the view in a bitmap.
+ View rootView = activity.getWindow().getDecorView().getRootView();
+ // rootView.setDrawingCacheEnabled(true);r
+ // rootView.setDrawingCacheEnabled(false);
+
+ Bitmap bitmap = null;
+
+ // Add the SurfaceView bit (see getAllTextureViews() below)
+ List<TextureView> tilingViews = getAllTextureViews(rootView);
+ if (tilingViews.size() > 0) {
+ bitmap = Bitmap.createBitmap(tilingViews.get(0).getHeight(), tilingViews.get(0).getWidth(),
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ for (TextureView TextureView : tilingViews) {
+ Bitmap b = TextureView.getBitmap(TextureView.getWidth(), TextureView.getHeight());
+ int[] location = new int[2];
+ TextureView.getLocationInWindow(location);
+ int[] location2 = new int[2];
+ TextureView.getLocationOnScreen(location2);
+ canvas.drawBitmap(b, 0, 0, null);
+ }
+ }
- // Save the bitmap in external storage
- String uniqueAbsolutePath = getUniqueAbsolutePath(testName);
- File outputFile = new File(uniqueAbsolutePath);
- OutputStream outputStream = null;
+ // Save the bitmap in external storage
+ String uniqueAbsolutePath = getUniqueAbsolutePath(testName);
+ File outputFile = new File(uniqueAbsolutePath);
+ OutputStream outputStream = null;
+ try {
+ outputStream = new FileOutputStream(outputFile);
+ bitmap.compress(DEFAULT_IMAGE_FORMAT, DEFAULT_IMAGE_QUALITY, outputStream);
+ outputStream.flush();
+ } catch (Exception exception) {
+
+ exception.printStackTrace();
+ } finally {
+ if (outputStream != null) {
try {
- outputStream = new FileOutputStream(outputFile);
- bitmap.compress(DEFAULT_IMAGE_FORMAT, DEFAULT_IMAGE_QUALITY, outputStream);
- outputStream.flush();
- } catch (Exception e) {
-
- e.printStackTrace();
- } finally {
- if (outputStream != null) {
- try {
- outputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
+ outputStream.close();
+ } catch (IOException ioException) {
+ ioException.printStackTrace();
}
+ }
}
-
- /*
- * The classic way of taking a screenshot (above) doesn't work with TextureView, this fixes it:
- * http://stackoverflow.com/questions/19704060/screen-capture-textureview-is-black-using-drawingcache
- */
-
- public static List<TextureView> getAllTextureViews(View view)
- {
- List<TextureView> tilingViews = new ArrayList<TextureView>();
- if (view instanceof TextureView) {
- tilingViews.add((TextureView)view);
- } else if(view instanceof ViewGroup) {
- ViewGroup viewGroup = (ViewGroup)view;
- for (int i = 0; i < viewGroup.getChildCount(); i++) {
- tilingViews.addAll(getAllTextureViews(viewGroup.getChildAt(i)));
- }
- }
-
- return tilingViews;
+ }
+
+ /*
+ * The classic way of taking a screenshot (above) doesn't work with TextureView, this fixes it:
+ * http://stackoverflow.com/questions/19704060/screen-capture-textureview-is-black-using-drawingcache
+ */
+
+ public static List<TextureView> getAllTextureViews(View view) {
+ List<TextureView> tilingViews = new ArrayList<TextureView>();
+ if (view instanceof TextureView) {
+ tilingViews.add((TextureView) view);
+ } else if (view instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) view;
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
+ tilingViews.addAll(getAllTextureViews(viewGroup.getChildAt(i)));
+ }
}
- /*
- * Utils
- */
+ return tilingViews;
+ }
- public static boolean isExternalStorageWritable() {
- // Checks if external storage is available for read and write
- String state = Environment.getExternalStorageState();
- return Environment.MEDIA_MOUNTED.equals(state);
- }
+ /*
+ * Utils
+ */
- private static String getUniqueAbsolutePath(String testName) {
- // A screenshot after every test vs. manual tests
- String filename = UUID.randomUUID().toString() + DEFAULT_IMAGE_EXTENSION;
- if (testName != null && !testName.isEmpty()) {
- filename = testName + DEFAULT_IMAGE_EXTENSION;
- }
+ public static boolean isExternalStorageWritable() {
+ // Checks if external storage is available for read and write
+ String state = Environment.getExternalStorageState();
+ return Environment.MEDIA_MOUNTED.equals(state);
+ }
- String externalPath = Environment.getExternalStorageDirectory().toString();
- String path = externalPath + File.separator + SCREENSHOT_FOLDER;
- File dir = new File(path);
- dir.mkdirs();
- path += File.separator + filename;
- Log.d(LOG_TAG, "Screenshot path: " + path);
- return path;
+ private static String getUniqueAbsolutePath(String testName) {
+ // A screenshot after every test vs. manual tests
+ String filename = UUID.randomUUID().toString() + DEFAULT_IMAGE_EXTENSION;
+ if (testName != null && !testName.isEmpty()) {
+ filename = testName + DEFAULT_IMAGE_EXTENSION;
}
+ String externalPath = Environment.getExternalStorageDirectory().toString();
+ String path = externalPath + File.separator + SCREENSHOT_FOLDER;
+ File dir = new File(path);
+ dir.mkdirs();
+ path += File.separator + filename;
+ Timber.d("Screenshot path: " + path);
+ return path;
+ }
+
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/TestConstants.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/TestConstants.java
new file mode 100644
index 0000000000..965f5d1443
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/TestConstants.java
@@ -0,0 +1,18 @@
+package com.mapbox.mapboxsdk.testapp.utils;
+
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+
+public class TestConstants {
+
+ public static final long ANIMATION_TEST_TIME = MapboxConstants.ANIMATION_DURATION * 2;
+
+ public static final double LAT_LNG_DELTA_LARGE = 0.1;
+ public static final double LAT_LNG_DELTA = 0.01;
+ public static final double BEARING_DELTA = 0.1;
+ public static final double TILT_DELTA = 0.1;
+ public static final double ZOOM_DELTA = 0.3;
+
+ public static final String TEXT_MARKER_TEXT = "Text";
+ public static final String TEXT_MARKER_TITLE = "Marker";
+ public static final String TEXT_MARKER_SNIPPET = "Snippet";
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ViewUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ViewUtils.java
index 01ee3e9b9f..5c4d5a03c3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ViewUtils.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ViewUtils.java
@@ -4,12 +4,19 @@ import android.support.annotation.IdRes;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
public class ViewUtils {
- public static void clickView(@IdRes int viewRes) {
- onView(withId(viewRes))
- .perform(click());
- }
+ public static void clickView(@IdRes int viewRes) {
+ onView(withId(viewRes))
+ .perform(click());
+ }
+
+ public static void checkViewIsDisplayed(int id) {
+ onView(withId(id))
+ .check(matches(isDisplayed()));
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
index c8a0de9826..684633bad1 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
@@ -13,6 +13,7 @@
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="@drawable/icon"
+ android:roundIcon="@drawable/ic_launcher_round"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
@@ -317,9 +318,9 @@
android:value="@string/category_fragment" />
</activity>
<activity
- android:name=".activity.maplayout.VideoViewActivity"
- android:description="@string/description_video_view"
- android:label="@string/activity_video_view">
+ android:name=".activity.maplayout.SimpleMapActivity"
+ android:description="@string/description_simple_map"
+ android:label="@string/activity_simple_map">
<meta-data
android:name="@string/category"
android:value="@string/category_maplayout" />
@@ -334,11 +335,11 @@
</activity>
<activity
android:name=".activity.style.CircleLayerActivity"
- android:description="@string/description_circle"
- android:label="@string/activity_circle">
+ android:description="@string/description_circle_layer"
+ android:label="@string/activity_circle_layer">
<meta-data
android:name="@string/category"
- android:value="@string/category_style" />
+ android:value="@string/category_style"/>
</activity>
<activity
android:name=".activity.style.GeoJsonClusteringActivity"
@@ -379,14 +380,6 @@
android:name="@string/category"
android:value="@string/category_imagegenerator" />
</activity>
- <activity
- android:name=".activity.maplayout.SurfaceViewMediaControlActivity"
- android:description="@string/description_surfaceview_mediacontrols"
- android:label="@string/activity_surfaceview_overlay">
- <meta-data
- android:name="@string/category"
- android:value="@string/category_maplayout" />
- </activity>
<!-- Features -->
<activity
@@ -406,6 +399,14 @@
android:value="@string/category_features" />
</activity>
<activity
+ android:name=".activity.feature.QueryRenderedFeaturesBoxSymbolCountActivity"
+ android:description="@string/description_query_rendered_features_box_symbol_count"
+ android:label="@string/activity_query_rendered_features_box_symbol_count">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_features" />
+ </activity>
+ <activity
android:name=".activity.feature.QueryRenderedFeaturesBoxHighlightActivity"
android:description="@string/description_query_rendered_features_box_highlight"
android:label="@string/activity_query_rendered_features_box_highlight">
@@ -437,10 +438,19 @@
android:name="@string/category"
android:value="@string/category_maplayout" />
</activity>
+ <activity
+ android:name=".activity.annotation.MarkerViewsInRectangleActivity"
+ android:description="@string/description_marker_view_rectangle"
+ android:label="@string/activity_marker_view_rectangle">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_annotation" />
+ </activity>
- <!-- For Unit tests -->
+ <!-- For Instrumentation tests -->
<activity android:name=".activity.style.RuntimeStyleTestActivity" />
<activity android:name=".activity.style.RuntimeStyleTimingTestActivity" />
+ <activity android:name=".activity.espresso.EspressoTestActivity" />
<!-- Configuration Settings -->
<meta-data
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java
index 5b4c730cfb..a10c6eaad3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java
@@ -3,34 +3,46 @@ package com.mapbox.mapboxsdk.testapp;
import android.app.Application;
import android.os.StrictMode;
-import com.mapbox.mapboxsdk.MapboxAccountManager;
+import com.mapbox.mapboxsdk.Mapbox;
import com.squareup.leakcanary.LeakCanary;
+import timber.log.Timber;
+
+import static timber.log.Timber.DebugTree;
+
public class MapboxApplication extends Application {
- @Override
- public void onCreate() {
- super.onCreate();
-
- if (LeakCanary.isInAnalyzerProcess(this)) {
- // This process is dedicated to LeakCanary for heap analysis.
- // You should not init your app in this process.
- return;
- }
- LeakCanary.install(this);
-
- StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
- .detectDiskReads()
- .detectDiskWrites()
- .detectNetwork()
- .penaltyLog()
- .build());
- StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
- .detectLeakedSqlLiteObjects()
- .penaltyLog()
- .penaltyDeath()
- .build());
-
- MapboxAccountManager.start(getApplicationContext(), getString(R.string.mapbox_access_token));
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ if (LeakCanary.isInAnalyzerProcess(this)) {
+ // This process is dedicated to LeakCanary for heap analysis.
+ // You should not init your app in this process.
+ return;
+ }
+ LeakCanary.install(this);
+
+ initializeLogger();
+
+ StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
+ .detectDiskReads()
+ .detectDiskWrites()
+ .detectNetwork()
+ .penaltyLog()
+ .build());
+ StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
+ .detectLeakedSqlLiteObjects()
+ .penaltyLog()
+ .penaltyDeath()
+ .build());
+
+ Mapbox.getInstance(getApplicationContext(), getString(R.string.mapbox_access_token));
+ }
+
+ private void initializeLogger() {
+ if (BuildConfig.DEBUG) {
+ Timber.plant(new DebugTree());
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java
index c3ade57986..9ba51e2694 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java
@@ -19,10 +19,11 @@ import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.View;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.adapter.FeatureAdapter;
import com.mapbox.mapboxsdk.testapp.adapter.FeatureSectionAdapter;
@@ -36,199 +37,199 @@ import java.util.List;
public class FeatureOverviewActivity extends AppCompatActivity {
- private static final String KEY_STATE_FEATURES = "featureList";
+ private static final String KEY_STATE_FEATURES = "featureList";
- private RecyclerView recyclerView;
- private FeatureSectionAdapter sectionAdapter;
- private List<Feature> features;
+ private RecyclerView recyclerView;
+ private FeatureSectionAdapter sectionAdapter;
+ private List<Feature> features;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- toolbar.setTitle(getString(R.string.app_name));
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setElevation(getResources().getDimension(R.dimen.toolbar_shadow));
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ toolbar.setTitle(getString(R.string.app_name));
+ setSupportActionBar(toolbar);
- recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
- recyclerView.setLayoutManager(new LinearLayoutManager(this));
- recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener());
- recyclerView.setHasFixedSize(true);
-
- ItemClickSupport.addTo(recyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
- @Override
- public void onItemClicked(RecyclerView recyclerView, int position, View view) {
- if (!sectionAdapter.isSectionHeaderPosition(position)) {
- int itemPosition = sectionAdapter.getConvertedPosition(position);
- Feature feature = features.get(itemPosition);
- if (feature.isRequiresLocationPermission()) {
- if (requestLocationPermission(itemPosition)) {
- return;
- }
- }
- startFeature(feature);
- }
- }
- });
-
- if (savedInstanceState == null) {
- loadFeatures();
- } else {
- features = savedInstanceState.getParcelableArrayList(KEY_STATE_FEATURES);
- onFeaturesLoaded(features);
- }
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setElevation(getResources().getDimension(R.dimen.toolbar_shadow));
}
- private void loadFeatures() {
- try {
- new LoadFeatureTask().execute(
- getPackageManager().getPackageInfo(getPackageName(),
- PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA));
- } catch (PackageManager.NameNotFoundException exception) {
- Log.e(MapboxConstants.TAG, "Could not resolve package info", exception);
- }
- }
-
- private void onFeaturesLoaded(List<Feature> featuresList) {
- features = featuresList;
-
- List<FeatureSectionAdapter.Section> sections = new ArrayList<>();
- String currentCat = "";
- for (int i = 0; i < features.size(); i++) {
- String category = features.get(i).getCategory();
- if (!currentCat.equals(category)) {
- sections.add(new FeatureSectionAdapter.Section(i, category));
- currentCat = category;
+ recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
+ recyclerView.setLayoutManager(new LinearLayoutManager(this));
+ recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener());
+ recyclerView.setHasFixedSize(true);
+
+ ItemClickSupport.addTo(recyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
+ @Override
+ public void onItemClicked(RecyclerView recyclerView, int position, View view) {
+ if (!sectionAdapter.isSectionHeaderPosition(position)) {
+ int itemPosition = sectionAdapter.getConvertedPosition(position);
+ Feature feature = features.get(itemPosition);
+ if (feature.isRequiresLocationPermission()) {
+ if (requestLocationPermission(itemPosition)) {
+ return;
}
+ }
+ startFeature(feature);
}
-
- FeatureSectionAdapter.Section[] dummy = new FeatureSectionAdapter.Section[sections.size()];
- sectionAdapter = new FeatureSectionAdapter(
- this, R.layout.section_main_layout, R.id.section_text, new FeatureAdapter(features));
- sectionAdapter.setSections(sections.toArray(dummy));
- recyclerView.setAdapter(sectionAdapter);
+ }
+ });
+
+ if (savedInstanceState == null) {
+ loadFeatures();
+ } else {
+ features = savedInstanceState.getParcelableArrayList(KEY_STATE_FEATURES);
+ onFeaturesLoaded(features);
}
-
- private void startFeature(Feature feature) {
- Intent intent = new Intent();
- intent.setComponent(new ComponentName(getPackageName(), feature.getName()));
- startActivity(intent);
+ }
+
+ private void loadFeatures() {
+ try {
+ new LoadFeatureTask().execute(
+ getPackageManager().getPackageInfo(getPackageName(),
+ PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA));
+ } catch (PackageManager.NameNotFoundException exception) {
+ Timber.e("Could not resolve package info", exception);
}
-
- private boolean requestLocationPermission(final int positionInList) {
- if ((ContextCompat.checkSelfPermission(FeatureOverviewActivity.this,
- Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
- || (ContextCompat.checkSelfPermission(FeatureOverviewActivity.this,
- Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
- ActivityCompat.requestPermissions(FeatureOverviewActivity.this, new String[]{
- Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, positionInList);
- return true;
- } else {
- return false;
- }
+ }
+
+ private void onFeaturesLoaded(List<Feature> featuresList) {
+ features = featuresList;
+
+ List<FeatureSectionAdapter.Section> sections = new ArrayList<>();
+ String currentCat = "";
+ for (int i = 0; i < features.size(); i++) {
+ String category = features.get(i).getCategory();
+ if (!currentCat.equals(category)) {
+ sections.add(new FeatureSectionAdapter.Section(i, category));
+ currentCat = category;
+ }
}
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- startFeature(features.get(requestCode));
- } else {
- Snackbar.make(
- findViewById(android.R.id.content),
- "Can't open without accepting the location permission.",
- Snackbar.LENGTH_SHORT).show();
- }
+ FeatureSectionAdapter.Section[] dummy = new FeatureSectionAdapter.Section[sections.size()];
+ sectionAdapter = new FeatureSectionAdapter(
+ this, R.layout.section_main_layout, R.id.section_text, new FeatureAdapter(features));
+ sectionAdapter.setSections(sections.toArray(dummy));
+ recyclerView.setAdapter(sectionAdapter);
+ }
+
+ private void startFeature(Feature feature) {
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName(getPackageName(), feature.getName()));
+ startActivity(intent);
+ }
+
+ private boolean requestLocationPermission(final int positionInList) {
+ if ((ContextCompat.checkSelfPermission(FeatureOverviewActivity.this,
+ Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
+ || (ContextCompat.checkSelfPermission(FeatureOverviewActivity.this,
+ Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
+ ActivityCompat.requestPermissions(FeatureOverviewActivity.this, new String[] {
+ Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, positionInList);
+ return true;
+ } else {
+ return false;
}
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putParcelableArrayList(KEY_STATE_FEATURES, (ArrayList<Feature>) features);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ startFeature(features.get(requestCode));
+ } else {
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Can't open without accepting the location permission.",
+ Snackbar.LENGTH_SHORT).show();
}
+ }
- private class LoadFeatureTask extends AsyncTask<PackageInfo, Void, List<Feature>> {
-
- @Override
- protected List<Feature> doInBackground(PackageInfo... params) {
- List<Feature> features = new ArrayList<>();
- PackageInfo app = params[0];
-
- String packageName = getApplicationContext().getPackageName();
- String metaDataKey = getString(R.string.category);
- for (ActivityInfo info : app.activities) {
- if (info.labelRes != 0 && info.name.startsWith(packageName)
- && !info.name.equals(FeatureOverviewActivity.class.getName())) {
- String label = getString(info.labelRes);
- String description = resolveString(info.descriptionRes);
- String category = resolveMetaData(info.metaData, metaDataKey);
- boolean requiresLocationPermission = requiresLocationPermission(label, category);
- features.add(new Feature(info.name, label, description, category, requiresLocationPermission));
- }
- }
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelableArrayList(KEY_STATE_FEATURES, (ArrayList<Feature>) features);
+ }
- if (!features.isEmpty()) {
- Comparator<Feature> comparator = new Comparator<Feature>() {
- @Override
- public int compare(Feature lhs, Feature rhs) {
- int result = lhs.getCategory().compareToIgnoreCase(rhs.getCategory());
- if (result == 0) {
- result = lhs.getLabel().compareToIgnoreCase(rhs.getLabel());
- }
- return result;
- }
- };
- Collections.sort(features, comparator);
- }
+ private class LoadFeatureTask extends AsyncTask<PackageInfo, Void, List<Feature>> {
- return features;
+ @Override
+ protected List<Feature> doInBackground(PackageInfo... params) {
+ List<Feature> features = new ArrayList<>();
+ PackageInfo app = params[0];
+
+ String packageName = getApplicationContext().getPackageName();
+ String metaDataKey = getString(R.string.category);
+ for (ActivityInfo info : app.activities) {
+ if (info.labelRes != 0 && info.name.startsWith(packageName)
+ && !info.name.equals(FeatureOverviewActivity.class.getName())) {
+ String label = getString(info.labelRes);
+ String description = resolveString(info.descriptionRes);
+ String category = resolveMetaData(info.metaData, metaDataKey);
+ boolean requiresLocationPermission = requiresLocationPermission(label, category);
+ features.add(new Feature(info.name, label, description, category, requiresLocationPermission));
}
-
- private String resolveMetaData(Bundle bundle, String key) {
- String category = null;
- if (bundle != null) {
- category = bundle.getString(key);
+ }
+
+ if (!features.isEmpty()) {
+ Comparator<Feature> comparator = new Comparator<Feature>() {
+ @Override
+ public int compare(Feature lhs, Feature rhs) {
+ int result = lhs.getCategory().compareToIgnoreCase(rhs.getCategory());
+ if (result == 0) {
+ result = lhs.getLabel().compareToIgnoreCase(rhs.getLabel());
}
- return category;
- }
+ return result;
+ }
+ };
+ Collections.sort(features, comparator);
+ }
- private String resolveString(@StringRes int stringRes) {
- try {
- return getString(stringRes);
- } catch (Resources.NotFoundException exception) {
- return "-";
- }
- }
+ return features;
+ }
- private boolean requiresLocationPermission(String name, String category) {
- final Resources resources = getResources();
+ private String resolveMetaData(Bundle bundle, String key) {
+ String category = null;
+ if (bundle != null) {
+ category = bundle.getString(key);
+ }
+ return category;
+ }
- List<String> requiresPermissionCategories = new ArrayList<String>() {
- {
- add(resources.getString(R.string.category_userlocation));
- }
- };
+ private String resolveString(@StringRes int stringRes) {
+ try {
+ return getString(stringRes);
+ } catch (Resources.NotFoundException exception) {
+ return "-";
+ }
+ }
- List<String> requiresPermissionActvities = new ArrayList<String>() {
- {
- add(resources.getString(R.string.activity_double_map));
- add(getString(R.string.activity_location_picker));
- add(getString(R.string.activity_car_driving));
- }
- };
+ private boolean requiresLocationPermission(String name, String category) {
+ final Resources resources = getResources();
- return requiresPermissionCategories.contains(category) || requiresPermissionActvities.contains(name);
+ List<String> requiresPermissionCategories = new ArrayList<String>() {
+ {
+ add(resources.getString(R.string.category_userlocation));
}
+ };
- @Override
- protected void onPostExecute(List<Feature> features) {
- super.onPostExecute(features);
- onFeaturesLoaded(features);
+ List<String> requiresPermissionActvities = new ArrayList<String>() {
+ {
+ add(resources.getString(R.string.activity_double_map));
+ add(getString(R.string.activity_location_picker));
+ add(getString(R.string.activity_car_driving));
}
+ };
+
+ return requiresPermissionCategories.contains(category) || requiresPermissionActvities.contains(name);
+ }
+
+ @Override
+ protected void onPostExecute(List<Feature> features) {
+ super.onPostExecute(features);
+ onFeaturesLoaded(features);
}
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AddRemoveMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AddRemoveMarkerActivity.java
index 811a87c0ad..6c56aa4a7a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AddRemoveMarkerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AddRemoveMarkerActivity.java
@@ -4,7 +4,9 @@ import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.MenuItem;
import com.mapbox.mapboxsdk.annotations.Icon;
@@ -13,7 +15,6 @@ import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -22,150 +23,161 @@ import com.mapbox.mapboxsdk.testapp.R;
public class AddRemoveMarkerActivity extends AppCompatActivity {
- public static final double THRESHOLD = 5.0;
-
- private MapView mapView;
- private MapboxMap mapboxMap;
- private double lastZoom;
- private boolean isShowingHighThresholdMarker;
- private boolean isShowingLowThresholdMarker;
-
- private MarkerOptions lowThresholdMarker;
- private MarkerOptions highThresholdMarker;
- private Marker activeMarker;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_add_remove_marker);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- final Icon icon1 = IconFactory.getInstance(this).fromResource(R.drawable.ic_arsenal);
- final Icon icon2 = IconFactory.getInstance(this).fromResource(R.drawable.ic_chelsea);
-
- lowThresholdMarker = new MarkerOptions()
- .icon(icon1)
- .position(new LatLng(-0.1, 0));
-
- highThresholdMarker = new MarkerOptions()
- .icon(icon2)
- .position(new LatLng(0.1, 0));
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap mapboxMap) {
- AddRemoveMarkerActivity.this.mapboxMap = mapboxMap;
- updateZoom(mapboxMap.getCameraPosition().zoom);
- mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.9f));
- mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
- @Override
- public void onCameraChange(CameraPosition position) {
- updateZoom(position.zoom);
- }
- });
- }
- });
- }
+ public static final double THRESHOLD = 5.0;
- private void updateZoom(double zoom) {
- if (lastZoom == zoom) {
- return;
- }
-
- lastZoom = zoom;
- if (zoom > THRESHOLD) {
- showHighThresholdMarker();
- } else {
- showLowThresholdMarker();
- }
- }
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private double lastZoom;
+ private boolean isShowingHighThresholdMarker;
+ private boolean isShowingLowThresholdMarker;
- private void showLowThresholdMarker() {
- if (isShowingLowThresholdMarker) {
- return;
- }
+ private MarkerOptions lowThresholdMarker;
+ private MarkerOptions highThresholdMarker;
+ private Marker activeMarker;
- isShowingLowThresholdMarker = true;
- isShowingHighThresholdMarker = false;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_add_remove_marker);
- if (activeMarker != null) {
- Log.d(MapboxConstants.TAG, "Remove marker with " + activeMarker.getId());
- mapboxMap.removeMarker(activeMarker);
- } else {
- Log.e(MapboxConstants.TAG, "active marker is null");
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- activeMarker = mapboxMap.addMarker(lowThresholdMarker);
- Log.d(MapboxConstants.TAG, "showLowThresholdMarker() " + activeMarker.getId());
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- private void showHighThresholdMarker() {
- if (isShowingHighThresholdMarker) {
- return;
- }
+ final Icon icon1 = IconFactory.getInstance(this).fromResource(R.drawable.ic_arsenal);
+ final Icon icon2 = IconFactory.getInstance(this).fromResource(R.drawable.ic_chelsea);
+
+ lowThresholdMarker = new MarkerOptions()
+ .icon(icon1)
+ .position(new LatLng(-0.1, 0));
+
+ highThresholdMarker = new MarkerOptions()
+ .icon(icon2)
+ .position(new LatLng(0.1, 0));
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap mapboxMap) {
+ AddRemoveMarkerActivity.this.mapboxMap = mapboxMap;
+ updateZoom(mapboxMap.getCameraPosition().zoom);
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.9f));
+ mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
+ @Override
+ public void onCameraChange(CameraPosition position) {
+ updateZoom(position.zoom);
+ }
+ });
+ }
+ });
+ }
- isShowingLowThresholdMarker = false;
- isShowingHighThresholdMarker = true;
+ private void updateZoom(double zoom) {
+ if (lastZoom == zoom) {
+ return;
+ }
- if (activeMarker != null) {
- Log.d(MapboxConstants.TAG, "Remove marker with " + activeMarker.getId());
- mapboxMap.removeMarker(activeMarker);
- } else {
- Log.e(MapboxConstants.TAG, "active marker is null");
- }
+ lastZoom = zoom;
+ if (zoom > THRESHOLD) {
+ showHighThresholdMarker();
+ } else {
+ showLowThresholdMarker();
+ }
+ }
- activeMarker = mapboxMap.addMarker(highThresholdMarker);
- Log.d(MapboxConstants.TAG, "showHighThresholdMarker() " + activeMarker.getId());
+ private void showLowThresholdMarker() {
+ if (isShowingLowThresholdMarker) {
+ return;
}
+ isShowingLowThresholdMarker = true;
+ isShowingHighThresholdMarker = false;
- @Override
- protected void onResume() {
- super.onResume();
- mapView.onResume();
+ if (activeMarker != null) {
+ Timber.d("Remove marker with " + activeMarker.getId());
+ mapboxMap.removeMarker(activeMarker);
+ } else {
+ Timber.e("active marker is null");
}
- @Override
- protected void onPause() {
- mapView.onPause();
- super.onPause();
- }
+ activeMarker = mapboxMap.addMarker(lowThresholdMarker);
+ Timber.d("showLowThresholdMarker() " + activeMarker.getId());
+ }
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ private void showHighThresholdMarker() {
+ if (isShowingHighThresholdMarker) {
+ return;
}
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
+ isShowingLowThresholdMarker = false;
+ isShowingHighThresholdMarker = true;
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ if (activeMarker != null) {
+ Timber.d("Remove marker with " + activeMarker.getId());
+ mapboxMap.removeMarker(activeMarker);
+ } else {
+ Timber.e("active marker is null");
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- }
- return super.onOptionsItemSelected(item);
+ activeMarker = mapboxMap.addMarker(highThresholdMarker);
+ Timber.d("showHighThresholdMarker() " + activeMarker.getId());
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
}
+ return super.onOptionsItemSelected(item);
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java
index 569d5298a4..50e6c44b6e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java
@@ -18,6 +18,7 @@ import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerView;
+import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLng;
@@ -26,226 +27,245 @@ import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.services.commons.models.Position;
+import com.mapbox.services.api.utils.turf.TurfMeasurement;
import java.util.Random;
public class AnimatedMarkerActivity extends AppCompatActivity {
- private MapView mapView;
- private MapboxMap mapboxMap;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
- private LatLng dupontCircle = new LatLng(38.90962, -77.04341);
+ private LatLng dupontCircle = new LatLng(38.90962, -77.04341);
- private Marker passengerMarker = null;
- private MarkerView carMarker = null;
+ private Marker passengerMarker = null;
+ private MarkerView carMarker = null;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_animated_marker);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
-
- @Override
- public void onMapReady(@NonNull final MapboxMap mapboxMap) {
- AnimatedMarkerActivity.this.mapboxMap = mapboxMap;
- setupMap();
-
- for (int i = 0; i < 10; i++) {
- addRandomCar();
- }
-
- addPassenger();
- addMainCar();
- animateMoveToPassenger(carMarker);
- }
- });
- }
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_animated_marker);
- private void setupMap() {
- CameraPosition cameraPosition = new CameraPosition.Builder()
- .target(dupontCircle)
- .zoom(15)
- .build();
- mapboxMap.setCameraPosition(cameraPosition);
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- private void addPassenger() {
- LatLng randomLatLng = getLatLngInBounds();
-
- if (passengerMarker == null) {
- Icon icon = IconFactory.getInstance(AnimatedMarkerActivity.this)
- .fromResource(R.drawable.ic_directions_run_black_24dp);
- passengerMarker = mapboxMap.addMarker(new MarkerViewOptions()
- .position(randomLatLng)
- .icon(icon));
- } else {
- passengerMarker.setPosition(randomLatLng);
- }
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- private void addMainCar() {
- LatLng randomLatLng = getLatLngInBounds();
-
- if (carMarker == null) {
- carMarker = createCarMarker(randomLatLng, R.drawable.ic_taxi_top);
- } else {
- carMarker.setPosition(randomLatLng);
- }
-
- // Make sure the car marker is selected so that it's always brought to the front (#5285)
- mapboxMap.selectMarker(carMarker);
- }
-
- private void animateMoveToPassenger(final MarkerView car) {
- ValueAnimator animator = animateMoveMarker(car, passengerMarker.getPosition());
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- addPassenger();
- animateMoveToPassenger(car);
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+
+ @Override
+ public void onMapReady(@NonNull final MapboxMap mapboxMap) {
+ AnimatedMarkerActivity.this.mapboxMap = mapboxMap;
+ setupMap();
+ mapView.post(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i < 10; i++) {
+ addRandomCar();
}
+ addPassenger();
+ addMainCar();
+ }
});
+ }
+ });
+ }
+
+ private void setupMap() {
+ CameraPosition cameraPosition = new CameraPosition.Builder()
+ .target(dupontCircle)
+ .zoom(15)
+ .build();
+ mapboxMap.setCameraPosition(cameraPosition);
+ }
+
+ private void addPassenger() {
+ LatLng randomLatLng = getLatLngInBounds();
+
+ if (passengerMarker == null) {
+ Icon icon = IconFactory.getInstance(AnimatedMarkerActivity.this)
+ .fromResource(R.drawable.ic_directions_run_black_24dp);
+ passengerMarker = mapboxMap.addMarker(new MarkerViewOptions()
+ .position(randomLatLng)
+ .icon(icon));
+ } else {
+ passengerMarker.setPosition(randomLatLng);
}
-
- protected void addRandomCar() {
- MarkerView car = createCarMarker(getLatLngInBounds(), R.drawable.ic_car_top);
- randomlyMoveMarker(car);
- }
-
- private void randomlyMoveMarker(final MarkerView marker) {
- ValueAnimator animator = animateMoveMarker(marker, getLatLngInBounds());
-
- //Add listener to restart animation on end
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- randomlyMoveMarker(marker);
- }
+ }
+
+ private void addMainCar() {
+ LatLng randomLatLng = getLatLngInBounds();
+
+ if (carMarker == null) {
+ carMarker = createCarMarker(randomLatLng, R.drawable.ic_taxi_top,
+ new MarkerViewManager.OnMarkerViewAddedListener() {
+ @Override
+ public void onViewAdded(@NonNull MarkerView markerView) {
+ // Make sure the car marker is selected so that it's always brought to the front (#5285)
+ mapboxMap.selectMarker(carMarker);
+ animateMoveToPassenger(carMarker);
+ }
});
- }
-
- private ValueAnimator animateMoveMarker(final MarkerView marker, LatLng to) {
- marker.setRotation((float) getBearing(marker.getPosition(), to));
-
- final ValueAnimator markerAnimator = ObjectAnimator.ofObject(
- marker, "position", new LatLngEvaluator(), marker.getPosition(), to);
- markerAnimator.setDuration((long) (10 * marker.getPosition().distanceTo(to)));
- markerAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
- // Start
- markerAnimator.start();
-
- return markerAnimator;
+ } else {
+ carMarker.setPosition(randomLatLng);
}
-
- private MarkerView createCarMarker(LatLng start, @DrawableRes int carResource) {
- Icon icon = IconFactory.getInstance(AnimatedMarkerActivity.this)
- .fromResource(carResource);
-
- //View Markers
- return mapboxMap.addMarker(new MarkerViewOptions()
- .position(start)
- .icon(icon));
-
- //GL Markers
+ }
+
+ private void animateMoveToPassenger(final MarkerView car) {
+ ValueAnimator animator = animateMoveMarker(car, passengerMarker.getPosition());
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ addPassenger();
+ animateMoveToPassenger(car);
+ }
+ });
+ }
+
+ protected void addRandomCar() {
+ createCarMarker(getLatLngInBounds(), R.drawable.ic_car_top, new MarkerViewManager.OnMarkerViewAddedListener() {
+ @Override
+ public void onViewAdded(@NonNull MarkerView markerView) {
+ randomlyMoveMarker(markerView);
+ }
+ });
+ }
+
+ private void randomlyMoveMarker(final MarkerView marker) {
+ ValueAnimator animator = animateMoveMarker(marker, getLatLngInBounds());
+
+ //Add listener to restart animation on end
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ randomlyMoveMarker(marker);
+ }
+ });
+ }
+
+ private ValueAnimator animateMoveMarker(final MarkerView marker, LatLng to) {
+ marker.setRotation((float) getBearing(marker.getPosition(), to));
+
+ final ValueAnimator markerAnimator = ObjectAnimator.ofObject(
+ marker, "position", new LatLngEvaluator(), marker.getPosition(), to);
+ markerAnimator.setDuration((long) (10 * marker.getPosition().distanceTo(to)));
+ markerAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
+
+ // Start
+ markerAnimator.start();
+
+ return markerAnimator;
+ }
+
+ private MarkerView createCarMarker(LatLng start, @DrawableRes int carResource,
+ MarkerViewManager.OnMarkerViewAddedListener listener) {
+ Icon icon = IconFactory.getInstance(AnimatedMarkerActivity.this)
+ .fromResource(carResource);
+
+ //View Markers
+ return mapboxMap.addMarker(new MarkerViewOptions()
+ .position(start)
+ .icon(icon), listener);
+
+ //GL Markers
// return mapboxMap.addMarker(new MarkerOptions()
// .position(start)
// .icon(icon));
+ }
+
+ private LatLng getLatLngInBounds() {
+ LatLngBounds bounds = mapboxMap.getProjection().getVisibleRegion().latLngBounds;
+ Random generator = new Random();
+ double randomLat = bounds.getLatSouth() + generator.nextDouble()
+ * (bounds.getLatNorth() - bounds.getLatSouth());
+ double randomLon = bounds.getLonWest() + generator.nextDouble()
+ * (bounds.getLonEast() - bounds.getLonWest());
+ return new LatLng(randomLat, randomLon);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
-
- private LatLng getLatLngInBounds() {
- LatLngBounds bounds = mapboxMap.getProjection().getVisibleRegion().latLngBounds;
- Random generator = new Random();
- double randomLat = bounds.getLatSouth() + generator.nextDouble()
- * (bounds.getLatNorth() - bounds.getLatSouth());
- double randomLon = bounds.getLonWest() + generator.nextDouble()
- * (bounds.getLonEast() - bounds.getLonWest());
- return new LatLng(randomLat, randomLon);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ /**
+ * Evaluator for LatLng pairs
+ */
+ private static class LatLngEvaluator implements TypeEvaluator<LatLng> {
+
+ private LatLng latLng = new LatLng();
@Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- /**
- * Evaluator for LatLng pairs
- */
- private static class LatLngEvaluator implements TypeEvaluator<LatLng> {
-
- private LatLng latLng = new LatLng();
-
- @Override
- public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
- latLng.setLatitude(startValue.getLatitude()
- + ((endValue.getLatitude() - startValue.getLatitude()) * fraction));
- latLng.setLongitude(startValue.getLongitude()
- + ((endValue.getLongitude() - startValue.getLongitude()) * fraction));
- return latLng;
- }
- }
-
- private double getBearing(LatLng from, LatLng to) {
- double degrees2radians = Math.PI / 180;
- double radians2degrees = 180 / Math.PI;
-
- double lon1 = degrees2radians * from.getLongitude();
- double lon2 = degrees2radians * to.getLongitude();
- double lat1 = degrees2radians * from.getLatitude();
- double lat2 = degrees2radians * to.getLatitude();
- double a = Math.sin(lon2 - lon1) * Math.cos(lat2);
- double b = Math.cos(lat1) * Math.sin(lat2)
- - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);
-
- return radians2degrees * Math.atan2(a, b);
+ public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
+ latLng.setLatitude(startValue.getLatitude()
+ + ((endValue.getLatitude() - startValue.getLatitude()) * fraction));
+ latLng.setLongitude(startValue.getLongitude()
+ + ((endValue.getLongitude() - startValue.getLongitude()) * fraction));
+ return latLng;
}
+ }
+
+ private double getBearing(LatLng from, LatLng to) {
+ return TurfMeasurement.bearing(
+ Position.fromCoordinates(from.getLongitude(), from.getLatitude()),
+ Position.fromCoordinates(to.getLongitude(), to.getLatitude())
+ );
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java
index 148207bab9..0d97289e56 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java
@@ -8,11 +8,14 @@ import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
+import android.support.v4.content.ContextCompat;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
@@ -43,247 +46,259 @@ import java.util.Random;
public class BulkMarkerActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
- private MapboxMap mapboxMap;
- private MapView mapView;
- private boolean customMarkerView;
- private List<LatLng> locations;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_marker_bulk);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayShowTitleEnabled(false);
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- BulkMarkerActivity.this.mapboxMap = mapboxMap;
-
- if (actionBar != null) {
- ArrayAdapter<CharSequence> spinnerAdapter = ArrayAdapter.createFromResource(
- actionBar.getThemedContext(), R.array.bulk_marker_list, android.R.layout.simple_spinner_item);
- spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- Spinner spinner = (Spinner) findViewById(R.id.spinner);
- spinner.setAdapter(spinnerAdapter);
- spinner.setOnItemSelectedListener(BulkMarkerActivity.this);
- }
- }
- });
+ private MapboxMap mapboxMap;
+ private MapView mapView;
+ private boolean customMarkerView;
+ private List<LatLng> locations;
- final View fab = findViewById(R.id.fab);
- if (fab != null) {
- fab.setOnClickListener(new FabClickListener());
- }
- }
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_marker_bulk);
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- int amount = Integer.valueOf(getResources().getStringArray(R.array.bulk_marker_list)[position]);
- if (locations == null) {
- new LoadLocationTask(this, amount).execute();
- } else {
- showMarkers(amount);
- }
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- private void onLatLngListLoaded(List<LatLng> latLngs, int amount) {
- locations = latLngs;
- showMarkers(amount);
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayShowTitleEnabled(false);
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- private void showMarkers(int amount) {
- mapboxMap.clear();
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ BulkMarkerActivity.this.mapboxMap = mapboxMap;
- if (locations.size() < amount) {
- amount = locations.size();
+ if (actionBar != null) {
+ ArrayAdapter<CharSequence> spinnerAdapter = ArrayAdapter.createFromResource(
+ actionBar.getThemedContext(), R.array.bulk_marker_list, android.R.layout.simple_spinner_item);
+ spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ Spinner spinner = (Spinner) findViewById(R.id.spinner);
+ spinner.setAdapter(spinnerAdapter);
+ spinner.setOnItemSelectedListener(BulkMarkerActivity.this);
}
+ }
+ });
- if (customMarkerView) {
- showViewMarkers(amount);
- } else {
- showGlMarkers(amount);
- }
+ final View fab = findViewById(R.id.fab);
+ if (fab != null) {
+ fab.setOnClickListener(new FabClickListener());
}
-
- private void showViewMarkers(int amount) {
- DecimalFormat formatter = new DecimalFormat("#.#####");
- Random random = new Random();
- int randomIndex;
-
- Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.ic_droppin_24dp, getTheme());
- int redColor = ResourcesCompat.getColor(getResources(), android.R.color.holo_red_dark, getTheme());
- drawable.setColorFilter(redColor, PorterDuff.Mode.SRC_IN);
- Icon icon = IconFactory.getInstance(this).fromDrawable(drawable);
-
- List<MarkerViewOptions> markerOptionsList = new ArrayList<>();
- for (int i = 0; i < amount; i++) {
- randomIndex = random.nextInt(locations.size());
- LatLng latLng = locations.get(randomIndex);
- MarkerViewOptions markerOptions = new MarkerViewOptions()
- .position(latLng)
- .icon(icon)
- .title(String.valueOf(i))
- .snippet(formatter.format(latLng.getLatitude()) + ", " + formatter.format(latLng.getLongitude()));
- markerOptionsList.add(markerOptions);
- }
- mapboxMap.addMarkerViews(markerOptionsList);
+ }
+
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ int amount = Integer.valueOf(getResources().getStringArray(R.array.bulk_marker_list)[position]);
+ if (locations == null) {
+ new LoadLocationTask(this, amount).execute();
+ } else {
+ showMarkers(amount);
}
+ }
- private void showGlMarkers(int amount) {
- List<MarkerOptions> markerOptionsList = new ArrayList<>();
- DecimalFormat formatter = new DecimalFormat("#.#####");
- Random random = new Random();
- int randomIndex;
-
- for (int i = 0; i < amount; i++) {
- randomIndex = random.nextInt(locations.size());
- LatLng latLng = locations.get(randomIndex);
- markerOptionsList.add(new MarkerOptions()
- .position(latLng)
- .title(String.valueOf(i))
- .snippet(formatter.format(latLng.getLatitude()) + ", " + formatter.format(latLng.getLongitude())));
- }
+ private void onLatLngListLoaded(List<LatLng> latLngs, int amount) {
+ locations = latLngs;
+ showMarkers(amount);
+ }
- mapboxMap.addMarkers(markerOptionsList);
- }
+ private void showMarkers(int amount) {
+ mapboxMap.clear();
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- // nothing selected, nothing to do!
+ if (locations.size() < amount) {
+ amount = locations.size();
}
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ if (customMarkerView) {
+ showViewMarkers(amount);
+ } else {
+ showGlMarkers(amount);
}
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ }
+
+ private void showViewMarkers(int amount) {
+ DecimalFormat formatter = new DecimalFormat("#.#####");
+ Random random = new Random();
+ int randomIndex;
+
+ Drawable drawable = ContextCompat.getDrawable(BulkMarkerActivity.this, R.drawable.ic_droppin_24dp);
+
+ int redColor = ResourcesCompat.getColor(getResources(), android.R.color.holo_red_dark, getTheme());
+ drawable.setColorFilter(redColor, PorterDuff.Mode.SRC_IN);
+ Icon icon = IconFactory.getInstance(this).fromDrawable(drawable);
+
+ List<MarkerViewOptions> markerOptionsList = new ArrayList<>();
+ for (int i = 0; i < amount; i++) {
+ randomIndex = random.nextInt(locations.size());
+ LatLng latLng = locations.get(randomIndex);
+ MarkerViewOptions markerOptions = new MarkerViewOptions()
+ .position(latLng)
+ .icon(icon)
+ .title(String.valueOf(i))
+ .snippet(formatter.format(latLng.getLatitude()) + ", " + formatter.format(latLng.getLongitude()));
+ markerOptionsList.add(markerOptions);
}
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ mapboxMap.addMarkerViews(markerOptionsList);
+ }
+
+ private void showGlMarkers(int amount) {
+ List<MarkerOptions> markerOptionsList = new ArrayList<>();
+ DecimalFormat formatter = new DecimalFormat("#.#####");
+ Random random = new Random();
+ int randomIndex;
+
+ for (int i = 0; i < amount; i++) {
+ randomIndex = random.nextInt(locations.size());
+ LatLng latLng = locations.get(randomIndex);
+ markerOptionsList.add(new MarkerOptions()
+ .position(latLng)
+ .title(String.valueOf(i))
+ .snippet(formatter.format(latLng.getLatitude()) + ", " + formatter.format(latLng.getLongitude())));
}
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ mapboxMap.addMarkers(markerOptionsList);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ // nothing selected, nothing to do!
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
+ private class FabClickListener implements View.OnClickListener {
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ public void onClick(final View view) {
+ if (mapboxMap != null) {
+ customMarkerView = true;
+
+ // remove fab
+ view.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ view.setVisibility(View.GONE);
+ }
+ }).start();
+
+ // reload markers
+ Spinner spinner = (Spinner) findViewById(R.id.spinner);
+ if (spinner != null) {
+ int amount = Integer.valueOf(
+ getResources().getStringArray(R.array.bulk_marker_list)[spinner.getSelectedItemPosition()]);
+ showMarkers(amount);
}
- }
- private class FabClickListener implements View.OnClickListener {
- @Override
- public void onClick(final View v) {
- if (mapboxMap != null) {
- customMarkerView = true;
-
- // remove fab
- v.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- v.setVisibility(View.GONE);
- }
- }).start();
-
- // reload markers
- Spinner spinner = (Spinner) findViewById(R.id.spinner);
- if (spinner != null) {
- int amount = Integer.valueOf(
- getResources().getStringArray(R.array.bulk_marker_list)[spinner.getSelectedItemPosition()]);
- showMarkers(amount);
- }
-
- mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
- @Override
- public void onMapChanged(@MapView.MapChange int change) {
- if (change == MapView.REGION_IS_CHANGING || change == MapView.REGION_DID_CHANGE) {
- if (!mapboxMap.getMarkerViewManager().getMarkerViewAdapters().isEmpty()) {
- TextView viewCountView = (TextView) findViewById(R.id.countView);
- viewCountView.setText("ViewCache size " + (mapView.getChildCount() - 5));
- }
- }
- }
- });
-
- mapboxMap.getMarkerViewManager().setOnMarkerViewClickListener(
- new MapboxMap.OnMarkerViewClickListener() {
- @Override
- public boolean onMarkerClick(
- @NonNull Marker marker, @NonNull View view, @NonNull MapboxMap.MarkerViewAdapter adapter) {
- Toast.makeText(
- BulkMarkerActivity.this,
- "Hello " + marker.getId(),
- Toast.LENGTH_SHORT).show();
- return false;
- }
- });
+ mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
+ @Override
+ public void onMapChanged(@MapView.MapChange int change) {
+ if (change == MapView.REGION_IS_CHANGING || change == MapView.REGION_DID_CHANGE) {
+ if (!mapboxMap.getMarkerViewManager().getMarkerViewAdapters().isEmpty()) {
+ TextView viewCountView = (TextView) findViewById(R.id.countView);
+ viewCountView.setText("ViewCache size " + (mapView.getChildCount() - 5));
+ }
}
- }
+ }
+ });
+
+ mapboxMap.getMarkerViewManager().setOnMarkerViewClickListener(
+ new MapboxMap.OnMarkerViewClickListener() {
+ @Override
+ public boolean onMarkerClick(
+ @NonNull Marker marker, @NonNull View view, @NonNull MapboxMap.MarkerViewAdapter adapter) {
+ Toast.makeText(
+ BulkMarkerActivity.this,
+ "Hello " + marker.getId(),
+ Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ });
+ }
}
+ }
- private static class LoadLocationTask extends AsyncTask<Void, Integer, List<LatLng>> {
+ private static class LoadLocationTask extends AsyncTask<Void, Integer, List<LatLng>> {
- private static final String TAG = "LoadLocationTask";
- private BulkMarkerActivity activity;
- private ProgressDialog progressDialog;
- private int amount;
+ private BulkMarkerActivity activity;
+ private ProgressDialog progressDialog;
+ private int amount;
- public LoadLocationTask(BulkMarkerActivity activity, int amount) {
- this.amount = amount;
- this.activity = activity;
- progressDialog = ProgressDialog.show(activity, "Loading", "Fetching markers", false);
- }
+ private LoadLocationTask(BulkMarkerActivity activity, int amount) {
+ this.amount = amount;
+ this.activity = activity;
+ progressDialog = ProgressDialog.show(activity, "Loading", "Fetching markers", false);
+ }
- @Override
- protected List<LatLng> doInBackground(Void... params) {
- try {
- String json = GeoParseUtil.loadStringFromAssets(activity.getApplicationContext(), "points.geojson");
- return GeoParseUtil.parseGeoJSONCoordinates(json);
- } catch (IOException | JSONException exception) {
- Log.e(TAG, "Could not add markers,", exception);
- return null;
- }
- }
+ @Override
+ protected List<LatLng> doInBackground(Void... params) {
+ try {
+ String json = GeoParseUtil.loadStringFromAssets(activity.getApplicationContext(), "points.geojson");
+ return GeoParseUtil.parseGeoJsonCoordinates(json);
+ } catch (IOException | JSONException exception) {
+ Timber.e("Could not add markers,", exception);
+ return null;
+ }
+ }
- @Override
- protected void onPostExecute(List<LatLng> locations) {
- super.onPostExecute(locations);
- activity.onLatLngListLoaded(locations, amount);
- progressDialog.hide();
- }
+ @Override
+ protected void onPostExecute(List<LatLng> locations) {
+ super.onPostExecute(locations);
+ activity.onLatLngListLoaded(locations, amount);
+ progressDialog.hide();
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java
index 3c3399168a..8446329e43 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java
@@ -13,8 +13,6 @@ import android.view.View;
import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
-import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -23,111 +21,123 @@ import com.mapbox.mapboxsdk.testapp.R;
public class DynamicMarkerChangeActivity extends AppCompatActivity {
- private static final LatLng LAT_LNG_CHELSEA = new LatLng(51.481670, -0.190849);
- private static final LatLng LAT_LNG_ARSENAL = new LatLng(51.555062, -0.108417);
+ private static final LatLng LAT_LNG_CHELSEA = new LatLng(51.481670, -0.190849);
+ private static final LatLng LAT_LNG_ARSENAL = new LatLng(51.555062, -0.108417);
- private MapView mapView;
- private MapboxMap mapboxMap;
- private IconFactory iconFactory;
- private Marker marker;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private IconFactory iconFactory;
+ private Marker marker;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_dynamic_marker);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_dynamic_marker);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- iconFactory = IconFactory.getInstance(this);
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.setTag(false);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- DynamicMarkerChangeActivity.this.mapboxMap = mapboxMap;
- // Create marker
- MarkerOptions markerOptions = new MarkerOptions()
- .position(LAT_LNG_CHELSEA)
- .icon(iconFactory.fromResource(R.drawable.ic_chelsea))
- .title(getString(R.string.dynamic_marker_chelsea_title))
- .snippet(getString(R.string.dynamic_marker_chelsea_snippet));
- marker = mapboxMap.addMarker(markerOptions);
- }
- });
-
- FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
- fab.setColorFilter(ContextCompat.getColor(this, R.color.primary));
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- updateMarker();
- }
- }
- });
- }
-
- private void updateMarker() {
- // update model
- boolean first = (boolean) mapView.getTag();
- mapView.setTag(!first);
-
- // update marker
- marker.setPosition(first ? LAT_LNG_CHELSEA : LAT_LNG_ARSENAL);
- marker.setIcon(iconFactory.fromResource(first ? R.drawable.ic_chelsea : R.drawable.ic_arsenal));
- marker.setTitle(first
- ? getString(R.string.dynamic_marker_chelsea_title) : getString(R.string.dynamic_marker_arsenal_title));
- marker.setSnippet(first
- ? getString(R.string.dynamic_marker_chelsea_snippet) : getString(R.string.dynamic_marker_arsenal_snippet));
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ iconFactory = IconFactory.getInstance(this);
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.setTag(false);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ DynamicMarkerChangeActivity.this.mapboxMap = mapboxMap;
+ // Create marker
+ MarkerOptions markerOptions = new MarkerOptions()
+ .position(LAT_LNG_CHELSEA)
+ .icon(iconFactory.fromResource(R.drawable.ic_chelsea))
+ .title(getString(R.string.dynamic_marker_chelsea_title))
+ .snippet(getString(R.string.dynamic_marker_chelsea_snippet));
+ marker = mapboxMap.addMarker(markerOptions);
+ }
+ });
+
+ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setColorFilter(ContextCompat.getColor(this, R.color.primary));
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (mapboxMap != null) {
+ updateMarker();
}
+ }
+ });
+ }
+
+ private void updateMarker() {
+ // update model
+ boolean first = (boolean) mapView.getTag();
+ mapView.setTag(!first);
+
+ // update marker
+ marker.setPosition(first ? LAT_LNG_CHELSEA : LAT_LNG_ARSENAL);
+ marker.setIcon(iconFactory.fromResource(first ? R.drawable.ic_chelsea : R.drawable.ic_arsenal));
+ marker.setTitle(first
+ ? getString(R.string.dynamic_marker_chelsea_title) : getString(R.string.dynamic_marker_arsenal_title));
+ marker.setSnippet(first
+ ? getString(R.string.dynamic_marker_chelsea_snippet) : getString(R.string.dynamic_marker_arsenal_snippet));
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java
index fe20b75a8d..f1dc7f8c0d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java
@@ -41,434 +41,458 @@ import java.util.Random;
public class MarkerViewActivity extends AppCompatActivity {
- private static final LatLng[] LAT_LNGS = new LatLng[]{
- new LatLng(38.897424, -77.036508),
- new LatLng(38.909698, -77.029642),
- new LatLng(38.907227, -77.036530),
- new LatLng(38.905607, -77.031916),
- new LatLng(38.889441, -77.050134),
- new LatLng(38.888000, -77.050000) //Slight overlap to show re-ordering on selection
- };
-
- private MapboxMap mapboxMap;
- private MapView mapView;
-
- // MarkerView location updates
- private MarkerView movingMarkerOne;
- private MarkerView movingMarkerTwo;
- private Random randomAnimator = new Random();
- private Handler locationUpdateHandler = new Handler();
- private Runnable moveMarkerRunnable = new MoveMarkerRunnable();
-
- // MarkerView rotate updates
- private MarkerView rotateMarker;
- private Handler rotateUpdateHandler = new Handler();
- private Runnable rotateMarkerRunnable = new RotateMarkerRunnable();
- private int rotation = 360;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_marker_view);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ private static final LatLng[] LAT_LNGS = new LatLng[] {
+ new LatLng(38.897424, -77.036508),
+ new LatLng(38.909698, -77.029642),
+ new LatLng(38.907227, -77.036530),
+ new LatLng(38.905607, -77.031916),
+ new LatLng(38.889441, -77.050134),
+ new LatLng(38.888000, -77.050000) //Slight overlap to show re-ordering on selection
+ };
+
+ private MapboxMap mapboxMap;
+ private MapView mapView;
+
+ // MarkerView location updates
+ private MarkerView movingMarkerOne;
+ private MarkerView movingMarkerTwo;
+ private Random randomAnimator = new Random();
+ private Handler locationUpdateHandler = new Handler();
+ private Runnable moveMarkerRunnable = new MoveMarkerRunnable();
+
+ // MarkerView rotate updates
+ private MarkerView rotateMarker;
+ private Handler rotateUpdateHandler = new Handler();
+ private Runnable rotateMarkerRunnable = new RotateMarkerRunnable();
+ private int rotation = 360;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_marker_view);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
+ final TextView viewCountView = (TextView) findViewById(R.id.countView);
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ MarkerViewActivity.this.mapboxMap = mapboxMap;
+
+ final MarkerViewManager markerViewManager = mapboxMap.getMarkerViewManager();
+
+ Icon usFlag = IconFactory.getInstance(MarkerViewActivity.this)
+ .fromResource(R.drawable.ic_us);
+
+ // add default ViewMarker markers
+ for (int i = 0; i < LAT_LNGS.length; i++) {
+ MarkerViewActivity.this.mapboxMap.addMarker(new MarkerViewOptions()
+ .position(LAT_LNGS[i])
+ .title(String.valueOf(i))
+ .alpha(0.5f)
+ .icon(usFlag)
+ );
}
- final TextView viewCountView = (TextView) findViewById(R.id.countView);
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- MarkerViewActivity.this.mapboxMap = mapboxMap;
-
- final MarkerViewManager markerViewManager = mapboxMap.getMarkerViewManager();
-
- Icon usFlag = IconFactory.getInstance(MarkerViewActivity.this)
- .fromResource(R.drawable.ic_us);
-
- // add default ViewMarker markers
- for (int i = 0; i < LAT_LNGS.length; i++) {
- MarkerViewActivity.this.mapboxMap.addMarker(new MarkerViewOptions()
- .position(LAT_LNGS[i])
- .title(String.valueOf(i))
- .alpha(0.5f)
- .icon(usFlag)
- );
- }
-
- // add custom ViewMarker
- CountryMarkerViewOptions options = new CountryMarkerViewOptions();
- options.flagRes(R.drawable.icon_burned);
- options.abbrevName("Mapbox");
- options.title("Hello");
- options.position(new LatLng(38.899774, -77.023237));
- options.flat(true);
- mapboxMap.addMarker(options);
-
- MarkerViewActivity.this.mapboxMap.addMarker(new MarkerOptions()
- .title("United States")
- .position(new LatLng(38.902580, -77.050102))
- );
-
- rotateMarker = MarkerViewActivity.this.mapboxMap.addMarker(new TextMarkerViewOptions()
- .text("A")
- .rotation(rotation = 270)
- .position(new LatLng(38.889876, -77.008849))
- );
- loopMarkerRotate();
-
-
- MarkerViewActivity.this.mapboxMap.addMarker(new TextMarkerViewOptions()
- .text("B")
- .position(new LatLng(38.907327, -77.041293))
- );
-
- MarkerViewActivity.this.mapboxMap.addMarker(new TextMarkerViewOptions()
- .text("C")
- .position(new LatLng(38.897642, -77.041980))
- );
-
- // if you want to customise a ViewMarker you need to extend ViewMarker and provide an adapter implementation
- // set adapters for child classes of ViewMarker
- markerViewManager.addMarkerViewAdapter(new CountryAdapter(MarkerViewActivity.this, mapboxMap));
- markerViewManager.addMarkerViewAdapter(new TextAdapter(MarkerViewActivity.this, mapboxMap));
-
- // add a change listener to validate the size of amount of child views
- mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
- @Override
- public void onMapChanged(@MapView.MapChange int change) {
- if (change == MapView.REGION_IS_CHANGING || change == MapView.REGION_DID_CHANGE) {
- if (!markerViewManager.getMarkerViewAdapters().isEmpty() && viewCountView != null) {
- viewCountView.setText("ViewCache size " + mapView.getMarkerViewContainer().getChildCount());
- }
- }
- }
- });
-
- // add a OnMarkerView click listener
- MarkerViewActivity.this.mapboxMap.getMarkerViewManager().setOnMarkerViewClickListener(new MapboxMap.OnMarkerViewClickListener() {
- @Override
- public boolean onMarkerClick(@NonNull Marker marker, @NonNull View view, @NonNull MapboxMap.MarkerViewAdapter adapter) {
- Toast.makeText(MarkerViewActivity.this, "Hello " + marker.getId(), Toast.LENGTH_SHORT).show();
- return false;
- }
- });
-
- movingMarkerOne = MarkerViewActivity.this.mapboxMap.addMarker(new MarkerViewOptions()
- .position(CarLocation.CAR_0_LNGS[0])
- .icon(IconFactory.getInstance(mapView.getContext())
- .fromResource(R.drawable.ic_chelsea))
- );
-
- movingMarkerTwo = mapboxMap.addMarker(new MarkerViewOptions()
- .position(CarLocation.CAR_1_LNGS[0])
- .icon(IconFactory.getInstance(mapView.getContext())
- .fromResource(R.drawable.ic_arsenal))
- );
+ // add custom ViewMarker
+ CountryMarkerViewOptions options = new CountryMarkerViewOptions();
+ options.flagRes(R.drawable.icon_burned);
+ options.abbrevName("Mapbox");
+ options.title("Hello");
+ options.position(new LatLng(38.899774, -77.023237));
+ options.flat(true);
+ mapboxMap.addMarker(options);
+
+ MarkerViewActivity.this.mapboxMap.addMarker(new MarkerOptions()
+ .title("United States")
+ .position(new LatLng(38.902580, -77.050102))
+ );
+
+ rotateMarker = MarkerViewActivity.this.mapboxMap.addMarker(new TextMarkerViewOptions()
+ .text("A")
+ .rotation(rotation = 270)
+ .position(new LatLng(38.889876, -77.008849))
+ );
+ loopMarkerRotate();
+
+
+ MarkerViewActivity.this.mapboxMap.addMarker(new TextMarkerViewOptions()
+ .text("B")
+ .position(new LatLng(38.907327, -77.041293))
+ );
+
+ MarkerViewActivity.this.mapboxMap.addMarker(new TextMarkerViewOptions()
+ .text("C")
+ .position(new LatLng(38.897642, -77.041980))
+ );
+
+ // if you want to customise a ViewMarker you need to extend ViewMarker and provide an adapter implementation
+ // set adapters for child classes of ViewMarker
+ markerViewManager.addMarkerViewAdapter(new CountryAdapter(MarkerViewActivity.this, mapboxMap));
+ markerViewManager.addMarkerViewAdapter(new TextAdapter(MarkerViewActivity.this, mapboxMap));
+
+ final ViewGroup markerViewContainer = markerViewManager.getMarkerViewContainer();
+
+ // add a change listener to validate the size of amount of child views
+ mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
+ @Override
+ public void onMapChanged(@MapView.MapChange int change) {
+ if (change == MapView.REGION_IS_CHANGING || change == MapView.REGION_DID_CHANGE) {
+ if (!markerViewManager.getMarkerViewAdapters().isEmpty() && viewCountView != null) {
+ viewCountView.setText("ViewCache size " + markerViewContainer.getChildCount());
+ }
}
+ }
});
- }
-
- private void loopMarkerRotate() {
- rotateUpdateHandler.postDelayed(rotateMarkerRunnable, 800);
- }
+ // add a OnMarkerView click listener
+ MarkerViewActivity.this.mapboxMap.getMarkerViewManager().setOnMarkerViewClickListener(
+ new MapboxMap.OnMarkerViewClickListener() {
+ @Override
+ public boolean onMarkerClick(@NonNull Marker marker, @NonNull View view,
+ @NonNull MapboxMap.MarkerViewAdapter adapter) {
+ Toast.makeText(MarkerViewActivity.this, "Hello " + marker.getId(), Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ });
+
+ movingMarkerOne = MarkerViewActivity.this.mapboxMap.addMarker(new MarkerViewOptions()
+ .position(CarLocation.CAR_0_LNGS[0])
+ .icon(IconFactory.getInstance(mapView.getContext())
+ .fromResource(R.drawable.ic_chelsea))
+ );
+
+ movingMarkerTwo = mapboxMap.addMarker(new MarkerViewOptions()
+ .position(CarLocation.CAR_1_LNGS[0])
+ .icon(IconFactory.getInstance(mapView.getContext())
+ .fromResource(R.drawable.ic_arsenal))
+ );
+
+ // allow more open infowindows at the same time
+ mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(true);
+
+ // add offscreen markers
+ Marker markerRightOffScreen = mapboxMap.addMarker(new MarkerOptions()
+ .setPosition(new LatLng(38.892846, -76.909399))
+ .title("InfoWindow")
+ .snippet("Offscreen, to the right of the Map."));
+
+ Marker markerRightBottomOffScreen = mapboxMap.addMarker(new MarkerOptions()
+ .setPosition(new LatLng(38.791645, -77.039006))
+ .title("InfoWindow")
+ .snippet("Offscreen, to the bottom of the Map"));
+
+ // open infowindow offscreen markers
+ mapboxMap.selectMarker(markerRightOffScreen);
+ mapboxMap.selectMarker(markerRightBottomOffScreen);
+ }
+ });
+ }
+
+ private void loopMarkerRotate() {
+ rotateUpdateHandler.postDelayed(rotateMarkerRunnable, 800);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ loopMarkerMove();
+ }
+
+ private void loopMarkerMove() {
+ locationUpdateHandler.postDelayed(moveMarkerRunnable, randomAnimator.nextInt(3000) + 1000);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ locationUpdateHandler.removeCallbacks(moveMarkerRunnable);
+ rotateUpdateHandler.removeCallbacks(rotateMarkerRunnable);
+ }
+
+ /**
+ * Updates the position of a Marker
+ */
+ private class MoveMarkerRunnable implements Runnable {
@Override
- protected void onStart() {
- super.onStart();
- loopMarkerMove();
+ public void run() {
+ int randomInteger = randomAnimator.nextInt(9);
+ if (randomAnimator.nextInt() % 2 == 0) {
+ movingMarkerOne.setPosition(CarLocation.CAR_0_LNGS[randomInteger]);
+ } else {
+ movingMarkerTwo.setPosition(CarLocation.CAR_1_LNGS[randomInteger]);
+ }
+ loopMarkerMove();
}
+ }
- private void loopMarkerMove() {
- locationUpdateHandler.postDelayed(moveMarkerRunnable, randomAnimator.nextInt(3000) + 1000);
- }
+ /**
+ * Updates the rotation of a Marker
+ */
+ private class RotateMarkerRunnable implements Runnable {
- @Override
- protected void onStop() {
- super.onStop();
- locationUpdateHandler.removeCallbacks(moveMarkerRunnable);
- rotateUpdateHandler.removeCallbacks(rotateMarkerRunnable);
- }
+ private static final int ROTATION_INCREASE_VALUE = 9;
- /**
- * Updates the position of a Marker
- */
- private class MoveMarkerRunnable implements Runnable {
- @Override
- public void run() {
- int i = randomAnimator.nextInt(9);
- if (randomAnimator.nextInt() % 2 == 0) {
- movingMarkerOne.setPosition(CarLocation.CAR_0_LNGS[i]);
- } else {
- movingMarkerTwo.setPosition(CarLocation.CAR_1_LNGS[i]);
- }
- loopMarkerMove();
- }
+ @Override
+ public void run() {
+ rotation -= ROTATION_INCREASE_VALUE;
+ if (rotation >= 0) {
+ rotation += 360;
+ }
+ rotateMarker.setRotation(rotation);
+ loopMarkerRotate();
}
+ }
- /**
- * Updates the rotation of a Marker
- */
- private class RotateMarkerRunnable implements Runnable {
+ /**
+ * Adapts a MarkerView to display an abbreviated name in a TextView and a flag in an ImageView.
+ */
+ private static class CountryAdapter extends MapboxMap.MarkerViewAdapter<CountryMarkerView> {
- private final static int ROTATION_INCREASE_VALUE = 9;
+ private LayoutInflater inflater;
+ private MapboxMap mapboxMap;
- @Override
- public void run() {
- rotation -= ROTATION_INCREASE_VALUE;
- if (rotation >= 0) {
- rotation += 360;
- }
- rotateMarker.setRotation(rotation);
- loopMarkerRotate();
- }
+ CountryAdapter(@NonNull Context context, @NonNull MapboxMap mapboxMap) {
+ super(context);
+ this.inflater = LayoutInflater.from(context);
+ this.mapboxMap = mapboxMap;
}
- /**
- * Adapts a MarkerView to display an abbreviated name in a TextView and a flag in an ImageView.
- */
- private static class CountryAdapter extends MapboxMap.MarkerViewAdapter<CountryMarkerView> {
-
- private LayoutInflater inflater;
- private MapboxMap mapboxMap;
-
- CountryAdapter(@NonNull Context context, @NonNull MapboxMap mapboxMap) {
- super(context);
- this.inflater = LayoutInflater.from(context);
- this.mapboxMap = mapboxMap;
- }
-
- @Nullable
- @Override
- public View getView(@NonNull CountryMarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
- ViewHolder viewHolder;
- if (convertView == null) {
- viewHolder = new ViewHolder();
- convertView = inflater.inflate(R.layout.view_custom_marker, parent, false);
- viewHolder.flag = (ImageView) convertView.findViewById(R.id.imageView);
- viewHolder.abbrev = (TextView) convertView.findViewById(R.id.textView);
- convertView.setTag(viewHolder);
- } else {
- viewHolder = (ViewHolder) convertView.getTag();
- }
- viewHolder.flag.setImageResource(marker.getFlagRes());
- viewHolder.abbrev.setText(marker.getAbbrevName());
- return convertView;
- }
-
- @Override
- public boolean onSelect(
- @NonNull final CountryMarkerView marker, @NonNull final View convertView, boolean reselectionForViewReuse) {
- convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ROTATION, 0, 360);
- rotateAnimator.setDuration(reselectionForViewReuse ? 0 : 350);
- rotateAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- convertView.setLayerType(View.LAYER_TYPE_NONE, null);
- mapboxMap.selectMarker(marker);
- }
- });
- rotateAnimator.start();
-
- // false indicates that we are calling selectMarker after our animation ourselves
- // true will let the system call it for you, which will result in showing an InfoWindow instantly
- return false;
- }
-
- @Override
- public void onDeselect(@NonNull CountryMarkerView marker, @NonNull final View convertView) {
- convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ROTATION, 360, 0);
- rotateAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- convertView.setLayerType(View.LAYER_TYPE_NONE, null);
- }
- });
- rotateAnimator.start();
- }
-
- private static class ViewHolder {
- ImageView flag;
- TextView abbrev;
- }
+ @Nullable
+ @Override
+ public View getView(@NonNull CountryMarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
+ ViewHolder viewHolder;
+ if (convertView == null) {
+ viewHolder = new ViewHolder();
+ convertView = inflater.inflate(R.layout.view_custom_marker, parent, false);
+ viewHolder.flag = (ImageView) convertView.findViewById(R.id.imageView);
+ viewHolder.abbrev = (TextView) convertView.findViewById(R.id.textView);
+ convertView.setTag(viewHolder);
+ } else {
+ viewHolder = (ViewHolder) convertView.getTag();
+ }
+ viewHolder.flag.setImageResource(marker.getFlagRes());
+ viewHolder.abbrev.setText(marker.getAbbrevName());
+ return convertView;
}
- /**
- * Adapts a MarkerView to display text in a TextView.
- */
- private static class TextAdapter extends MapboxMap.MarkerViewAdapter<TextMarkerView> {
-
- private LayoutInflater inflater;
- private MapboxMap mapboxMap;
-
- TextAdapter(@NonNull Context context, @NonNull MapboxMap mapboxMap) {
- super(context);
- this.inflater = LayoutInflater.from(context);
- this.mapboxMap = mapboxMap;
- }
-
- @Nullable
+ @Override
+ public boolean onSelect(
+ @NonNull final CountryMarkerView marker, @NonNull final View convertView, boolean reselectionForViewReuse) {
+ convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ROTATION, 0, 360);
+ rotateAnimator.setDuration(reselectionForViewReuse ? 0 : 350);
+ rotateAnimator.addListener(new AnimatorListenerAdapter() {
@Override
- public View getView(@NonNull TextMarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
- ViewHolder viewHolder;
- if (convertView == null) {
- viewHolder = new ViewHolder();
- convertView = inflater.inflate(R.layout.view_text_marker, parent, false);
- viewHolder.textView = (TextView) convertView.findViewById(R.id.textView);
- convertView.setTag(viewHolder);
- } else {
- viewHolder = (ViewHolder) convertView.getTag();
- }
- viewHolder.textView.setText(marker.getText());
- return convertView;
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ convertView.setLayerType(View.LAYER_TYPE_NONE, null);
+ mapboxMap.selectMarker(marker);
}
+ });
+ rotateAnimator.start();
- @Override
- public boolean onSelect(
- @NonNull final TextMarkerView marker, @NonNull final View convertView, boolean reselectionForViewReuse) {
- animateGrow(marker, convertView, 0);
-
- // false indicates that we are calling selectMarker after our animation ourselves
- // true will let the system call it for you, which will result in showing an InfoWindow instantly
- return false;
- }
+ // false indicates that we are calling selectMarker after our animation ourselves
+ // true will let the system call it for you, which will result in showing an InfoWindow instantly
+ return false;
+ }
+ @Override
+ public void onDeselect(@NonNull CountryMarkerView marker, @NonNull final View convertView) {
+ convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ROTATION, 360, 0);
+ rotateAnimator.addListener(new AnimatorListenerAdapter() {
@Override
- public void onDeselect(@NonNull TextMarkerView marker, @NonNull final View convertView) {
- animateShrink(convertView, 350);
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ convertView.setLayerType(View.LAYER_TYPE_NONE, null);
}
+ });
+ rotateAnimator.start();
+ }
- @Override
- public boolean prepareViewForReuse(@NonNull MarkerView marker, @NonNull View convertView) {
- // this method is called before a view will be reused, we need to restore view state
- // as we have scaled the view in onSelect. If not correctly applied other MarkerView will
- // become large since these have been recycled
-
- // cancel ongoing animation
- convertView.animate().cancel();
-
- if (marker.isSelected()) {
- // shrink view to be able to be reused
- animateShrink(convertView, 0);
- }
-
- // true if you want reuse to occur automatically, false if you want to manage this yourself
- return true;
- }
+ private static class ViewHolder {
+ ImageView flag;
+ TextView abbrev;
+ }
+ }
- private void animateGrow(@NonNull final MarkerView marker, @NonNull final View convertView, int duration) {
- convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- Animator animator = AnimatorInflater.loadAnimator(convertView.getContext(), R.animator.scale_up);
- animator.setDuration(duration);
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- convertView.setLayerType(View.LAYER_TYPE_NONE, null);
- mapboxMap.selectMarker(marker);
- }
- });
- animator.setTarget(convertView);
- animator.start();
- }
+ /**
+ * Adapts a MarkerView to display text in a TextView.
+ */
+ public static class TextAdapter extends MapboxMap.MarkerViewAdapter<TextMarkerView> {
- private void animateShrink(@NonNull final View convertView, int duration) {
- convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- Animator animator = AnimatorInflater.loadAnimator(convertView.getContext(), R.animator.scale_down);
- animator.setDuration(duration);
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- convertView.setLayerType(View.LAYER_TYPE_NONE, null);
- }
- });
- animator.setTarget(convertView);
- animator.start();
- }
+ private LayoutInflater inflater;
+ private MapboxMap mapboxMap;
- private static class ViewHolder {
- TextView textView;
- }
+ public TextAdapter(@NonNull Context context, @NonNull MapboxMap mapboxMap) {
+ super(context);
+ this.inflater = LayoutInflater.from(context);
+ this.mapboxMap = mapboxMap;
}
-
+ @Nullable
@Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
+ public View getView(@NonNull TextMarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
+ ViewHolder viewHolder;
+ if (convertView == null) {
+ viewHolder = new ViewHolder();
+ convertView = inflater.inflate(R.layout.view_text_marker, parent, false);
+ viewHolder.textView = (TextView) convertView.findViewById(R.id.textView);
+ convertView.setTag(viewHolder);
+ } else {
+ viewHolder = (ViewHolder) convertView.getTag();
+ }
+ viewHolder.textView.setText(marker.getText());
+ return convertView;
}
@Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ public boolean onSelect(
+ @NonNull final TextMarkerView marker, @NonNull final View convertView, boolean reselectionForViewReuse) {
+ animateGrow(marker, convertView, 0);
+
+ // false indicates that we are calling selectMarker after our animation ourselves
+ // true will let the system call it for you, which will result in showing an InfoWindow instantly
+ return false;
}
@Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ public void onDeselect(@NonNull TextMarkerView marker, @NonNull final View convertView) {
+ animateShrink(convertView, 350);
}
@Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ public boolean prepareViewForReuse(@NonNull MarkerView marker, @NonNull View convertView) {
+ // this method is called before a view will be reused, we need to restore view state
+ // as we have scaled the view in onSelect. If not correctly applied other MarkerView will
+ // become large since these have been recycled
+
+ // cancel ongoing animation
+ convertView.animate().cancel();
+
+ if (marker.isSelected()) {
+ // shrink view to be able to be reused
+ animateShrink(convertView, 0);
+ }
+
+ // true if you want reuse to occur automatically, false if you want to manage this yourself
+ return true;
}
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ private void animateGrow(@NonNull final MarkerView marker, @NonNull final View convertView, int duration) {
+ convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ Animator animator = AnimatorInflater.loadAnimator(convertView.getContext(), R.animator.scale_up);
+ animator.setDuration(duration);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ convertView.setLayerType(View.LAYER_TYPE_NONE, null);
+ mapboxMap.selectMarker(marker);
+ }
+ });
+ animator.setTarget(convertView);
+ animator.start();
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ private void animateShrink(@NonNull final View convertView, int duration) {
+ convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ Animator animator = AnimatorInflater.loadAnimator(convertView.getContext(), R.animator.scale_down);
+ animator.setDuration(duration);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ convertView.setLayerType(View.LAYER_TYPE_NONE, null);
}
+ });
+ animator.setTarget(convertView);
+ animator.start();
}
- private static class CarLocation {
-
- static LatLng[] CAR_0_LNGS = new LatLng[]{
- new LatLng(38.92334425495122, -77.0533673443786),
- new LatLng(38.9234737236897, -77.05389484528261),
- new LatLng(38.9257094658146, -76.98819752280579),
- new LatLng(38.8324328369647, -77.00690648325929),
- new LatLng(38.87540698725855, -77.0093148713099),
- new LatLng(38.96499498141065, -77.07707916040054),
- new LatLng(38.90794910679896, -76.99695304153806),
- new LatLng(38.86234025281626, -76.9950528034839),
- new LatLng(38.862930274733635, -76.99647808241964)
- };
-
- static LatLng[] CAR_1_LNGS = new LatLng[]{
- new LatLng(38.94237975070426, -76.98324549005675),
- new LatLng(38.941520236084486, -76.98234257804742),
- new LatLng(38.85972219720714, -76.98955808483929),
- new LatLng(38.944289166113776, -76.98584257252891),
- new LatLng(38.94375860578053, -76.98470344318412),
- new LatLng(38.943167431929645, -76.98373163938666),
- new LatLng(38.882834728904605, -77.02862535635137),
- new LatLng(38.882869724926245, -77.02992539231113),
- new LatLng(38.9371988177896, -76.97786740676564)
- };
+ private static class ViewHolder {
+ TextView textView;
}
+ }
+
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private static class CarLocation {
+
+ static LatLng[] CAR_0_LNGS = new LatLng[] {
+ new LatLng(38.92334425495122, -77.0533673443786),
+ new LatLng(38.9234737236897, -77.05389484528261),
+ new LatLng(38.9257094658146, -76.98819752280579),
+ new LatLng(38.8324328369647, -77.00690648325929),
+ new LatLng(38.87540698725855, -77.0093148713099),
+ new LatLng(38.96499498141065, -77.07707916040054),
+ new LatLng(38.90794910679896, -76.99695304153806),
+ new LatLng(38.86234025281626, -76.9950528034839),
+ new LatLng(38.862930274733635, -76.99647808241964)
+ };
+
+ static LatLng[] CAR_1_LNGS = new LatLng[] {
+ new LatLng(38.94237975070426, -76.98324549005675),
+ new LatLng(38.941520236084486, -76.98234257804742),
+ new LatLng(38.85972219720714, -76.98955808483929),
+ new LatLng(38.944289166113776, -76.98584257252891),
+ new LatLng(38.94375860578053, -76.98470344318412),
+ new LatLng(38.943167431929645, -76.98373163938666),
+ new LatLng(38.882834728904605, -77.02862535635137),
+ new LatLng(38.882869724926245, -77.02992539231113),
+ new LatLng(38.9371988177896, -76.97786740676564)
+ };
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewScaleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewScaleActivity.java
index e4a3b3b2cb..53e352c2e6 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewScaleActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewScaleActivity.java
@@ -8,10 +8,12 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;
+import android.widget.Toast;
import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.annotations.MarkerView;
+import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
@@ -23,120 +25,155 @@ import java.util.Locale;
public class MarkerViewScaleActivity extends AppCompatActivity implements OnMapReadyCallback {
- private MapboxMap mapboxMap;
- private MapView mapView;
- private View markerView;
+ private MapboxMap mapboxMap;
+ private MapView mapView;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_marker_view_scale);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ private MarkerView markerView;
+ private MarkerViewManager markerViewManager;
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_marker_view_scale);
- final SeekBar xBar = (SeekBar) findViewById(R.id.seekbar_factor);
- TextView textView = (TextView) findViewById(R.id.textview_factor);
- xBar.setOnSeekBarChangeListener(new FactorChangeListener(textView));
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- Icon icon = IconFactory.getInstance(MarkerViewScaleActivity.this)
- .fromResource(R.drawable.ic_circle);
-
- MarkerView marker = mapboxMap.addMarker(new MarkerViewOptions()
- .position(new LatLng(38.907192, -77.036871))
- .icon(icon)
- .flat(true));
-
- markerView = mapboxMap.getMarkerViewManager().getView(marker);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ markerViewManager = map.getMarkerViewManager();
+
+ final SeekBar xBar = (SeekBar) findViewById(R.id.seekbar_factor);
+ final TextView textView = (TextView) findViewById(R.id.textview_factor);
+
+ // We need to listen to a render event to be sure
+ // the View of the Marker has been added to the map
+ mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
+ @Override
+ public void onMapChanged(@MapView.MapChange int change) {
+ if (isMarkerRendered()) {
+ Toast.makeText(MarkerViewScaleActivity.this, "MarkerView is ready", Toast.LENGTH_SHORT).show();
+ View view = markerViewManager.getView(markerView);
+ xBar.setOnSeekBarChangeListener(new FactorChangeListener(view, textView));
+ xBar.setClickable(true);
+ mapView.removeOnMapChangedListener(this);
}
+ }
+
+ private boolean isMarkerRendered() {
+ return markerView != null && markerViewManager.getView(markerView) != null;
+ }
+ });
+
+ Icon icon = IconFactory.getInstance(MarkerViewScaleActivity.this)
+ .fromResource(R.drawable.ic_circle);
+
+ markerView = mapboxMap.addMarker(new MarkerViewOptions()
+ .position(new LatLng(38.907192, -77.036871))
+ .icon(icon)
+ .flat(true));
+ }
+
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onStart() {
+ super.onResume();
+ mapView.onStart();
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ private static class FactorChangeListener implements SeekBar.OnSeekBarChangeListener {
+
+ private TextView textView;
+ private View view;
+
+ FactorChangeListener(View view, TextView textView) {
+ this.view = view;
+ this.textView = textView;
}
@Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ float newScale = getScale(progress);
+ textView.setText(String.format(Locale.US, "Scale: %.1f", newScale));
+ if (view != null) {
+ view.setScaleX(newScale);
+ view.setScaleY(newScale);
+ }
}
@Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Not used
}
@Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Not used
}
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- private class FactorChangeListener implements SeekBar.OnSeekBarChangeListener {
-
- private TextView textView;
-
- public FactorChangeListener(TextView textView) {
- this.textView = textView;
- }
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- float newScale = getScale(progress);
- textView.setText(String.format(Locale.US, "Scale: %.1f", newScale));
- if (MarkerViewScaleActivity.this.markerView != null) {
- markerView.setScaleX(newScale);
- markerView.setScaleY(newScale);
- }
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- // Not used
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- // Not used
- }
-
- private float getScale(int progress) {
- float scale = 1.0f * progress / 25;
- return scale < 1.0 ? 1.0f : scale;
- }
+ private float getScale(int progress) {
+ float scale = 1.0f * progress / 25;
+ return scale < 1.0 ? 1.0f : scale;
}
+ }
-}
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewsInRectangleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewsInRectangleActivity.java
new file mode 100644
index 0000000000..99a0465092
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewsInRectangleActivity.java
@@ -0,0 +1,133 @@
+package com.mapbox.mapboxsdk.testapp.activity.annotation;
+
+import android.graphics.RectF;
+import android.os.Bundle;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Toast;
+
+import com.mapbox.mapboxsdk.annotations.MarkerView;
+import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.testapp.R;
+
+import java.util.List;
+
+import timber.log.Timber;
+
+public class MarkerViewsInRectangleActivity extends AppCompatActivity implements OnMapReadyCallback,
+ View.OnClickListener {
+
+ public MapView mapView;
+ private MapboxMap mapboxMap;
+ private View selectionBox;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_marker_view_in_rect);
+ setupActionBar();
+
+ selectionBox = findViewById(R.id.selection_box);
+
+ //Initialize map as normal
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(MapboxMap mapboxMap) {
+ MarkerViewsInRectangleActivity.this.mapboxMap = mapboxMap;
+ selectionBox.setOnClickListener(this);
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.0907, 5.1214), 16));
+ mapboxMap.addMarker(new MarkerViewOptions().position(new LatLng(52.0907, 5.1214)));
+ }
+
+ @Override
+ public void onClick(View view) {
+ //Query
+ int top = selectionBox.getTop() - mapView.getTop();
+ int left = selectionBox.getLeft() - mapView.getLeft();
+ RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
+ Timber.i(String.format("Querying box %s", box));
+ List<MarkerView> markers = mapboxMap.getMarkerViewsInRect(box);
+
+ //Show count
+ Toast.makeText(
+ MarkerViewsInRectangleActivity.this,
+ String.format("%s markers inside box", markers.size()),
+ Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private void setupActionBar() {
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java
index dd80b2ba5a..16efa9f190 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java
@@ -38,149 +38,161 @@ import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.C
*/
public class PolygonActivity extends AppCompatActivity implements OnMapReadyCallback {
- private MapView mapView;
- private MapboxMap mapboxMap;
-
- private Polygon polygon;
- private boolean fullAlpha = true;
- private boolean visible = true;
- private boolean color = true;
- private boolean allPoints;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_polygon);
- ToolbarComposer.initDefaultUpToolbar(this, R.id.toolbar);
-
- // configure inital map state
- MapboxMapOptions options = new MapboxMapOptions()
- .attributionTintColor(RED_COLOR)
- // deprecated feature!
- .textureMode(true)
- .compassFadesWhenFacingNorth(false)
- .styleUrl(Style.MAPBOX_STREETS)
- .camera(new CameraPosition.Builder()
- .target(new LatLng(45.520486, -122.673541))
- .zoom(12)
- .tilt(40)
- .build());
-
- // create map
- mapView = new MapView(this, options);
- mapView.setId(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
-
- // add to layout
- ViewGroup container = (ViewGroup) findViewById(R.id.container);
- if (container != null) {
- container.addView(mapView);
- }
- }
-
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- polygon = mapboxMap.addPolygon(new PolygonOptions()
- .addAll(STAR_SHAPE_POINTS)
- .fillColor(BLUE_COLOR));
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+
+ private Polygon polygon;
+ private boolean fullAlpha = true;
+ private boolean visible = true;
+ private boolean color = true;
+ private boolean allPoints;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_polygon);
+ ToolbarComposer.initDefaultUpToolbar(this, R.id.toolbar);
+
+ // configure inital map state
+ MapboxMapOptions options = new MapboxMapOptions()
+ .attributionTintColor(RED_COLOR)
+ // deprecated feature!
+ .textureMode(true)
+ .compassFadesWhenFacingNorth(false)
+ .styleUrl(Style.MAPBOX_STREETS)
+ .camera(new CameraPosition.Builder()
+ .target(new LatLng(45.520486, -122.673541))
+ .zoom(12)
+ .tilt(40)
+ .build());
+
+ // create map
+ mapView = new MapView(this, options);
+ mapView.setId(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+
+ // add to layout
+ ViewGroup container = (ViewGroup) findViewById(R.id.container);
+ if (container != null) {
+ container.addView(mapView);
}
+ }
+
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ polygon = mapboxMap.addPolygon(new PolygonOptions()
+ .addAll(STAR_SHAPE_POINTS)
+ .fillColor(BLUE_COLOR));
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
+ case R.id.action_id_alpha:
+ fullAlpha = !fullAlpha;
+ polygon.setAlpha(fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA);
+ return true;
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
-
- case R.id.action_id_alpha:
- fullAlpha = !fullAlpha;
- polygon.setAlpha(fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA);
- return true;
-
- case R.id.action_id_visible:
- visible = !visible;
- polygon.setAlpha(visible ? (fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA) : NO_ALPHA);
- return true;
-
- case R.id.action_id_points:
- allPoints = !allPoints;
- polygon.setPoints(allPoints ? STAR_SHAPE_POINTS : BROKEN_SHAPE_POINTS);
- return true;
-
- case R.id.action_id_color:
- color = !color;
- polygon.setFillColor(color ? BLUE_COLOR : RED_COLOR);
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
+ case R.id.action_id_visible:
+ visible = !visible;
+ polygon.setAlpha(visible ? (fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA) : NO_ALPHA);
+ return true;
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_polygon, menu);
+ case R.id.action_id_points:
+ allPoints = !allPoints;
+ polygon.setPoints(allPoints ? STAR_SHAPE_POINTS : BROKEN_SHAPE_POINTS);
return true;
- }
- final static class Config {
- static final int BLUE_COLOR = Color.parseColor("#3bb2d0");
- static final int RED_COLOR = Color.parseColor("#AF0000");
-
- static final float FULL_ALPHA = 1.0f;
- static final float PARTIAL_ALPHA = 0.5f;
- static final float NO_ALPHA = 0.0f;
-
- static final List<LatLng> STAR_SHAPE_POINTS = new ArrayList<LatLng>() {
- {
- add(new LatLng(45.522585, -122.685699));
- add(new LatLng(45.534611, -122.708873));
- add(new LatLng(45.530883, -122.678833));
- add(new LatLng(45.547115, -122.667503));
- add(new LatLng(45.530643, -122.660121));
- add(new LatLng(45.533529, -122.636260));
- add(new LatLng(45.521743, -122.659091));
- add(new LatLng(45.510677, -122.648792));
- add(new LatLng(45.515008, -122.664070));
- add(new LatLng(45.502496, -122.669048));
- add(new LatLng(45.515369, -122.678489));
- add(new LatLng(45.506346, -122.702007));
- add(new LatLng(45.522585, -122.685699));
- }
- };
-
- static final List<LatLng> BROKEN_SHAPE_POINTS =
- STAR_SHAPE_POINTS.subList(0, STAR_SHAPE_POINTS.size() - 3);
+ case R.id.action_id_color:
+ color = !color;
+ polygon.setFillColor(color ? BLUE_COLOR : RED_COLOR);
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_polygon, menu);
+ return true;
+ }
+
+ static final class Config {
+ static final int BLUE_COLOR = Color.parseColor("#3bb2d0");
+ static final int RED_COLOR = Color.parseColor("#AF0000");
+
+ static final float FULL_ALPHA = 1.0f;
+ static final float PARTIAL_ALPHA = 0.5f;
+ static final float NO_ALPHA = 0.0f;
+
+ static final List<LatLng> STAR_SHAPE_POINTS = new ArrayList<LatLng>() {
+ {
+ add(new LatLng(45.522585, -122.685699));
+ add(new LatLng(45.534611, -122.708873));
+ add(new LatLng(45.530883, -122.678833));
+ add(new LatLng(45.547115, -122.667503));
+ add(new LatLng(45.530643, -122.660121));
+ add(new LatLng(45.533529, -122.636260));
+ add(new LatLng(45.521743, -122.659091));
+ add(new LatLng(45.510677, -122.648792));
+ add(new LatLng(45.515008, -122.664070));
+ add(new LatLng(45.502496, -122.669048));
+ add(new LatLng(45.515369, -122.678489));
+ add(new LatLng(45.506346, -122.702007));
+ add(new LatLng(45.522585, -122.685699));
+ }
+ };
+
+ static final List<LatLng> BROKEN_SHAPE_POINTS =
+ STAR_SHAPE_POINTS.subList(0, STAR_SHAPE_POINTS.size() - 3);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java
index dabac927d9..44f11ca674 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java
@@ -24,192 +24,205 @@ import java.util.List;
public class PolylineActivity extends AppCompatActivity {
- private static final String STATE_POLYLINE_OPTIONS = "polylineOptions";
-
- private static final LatLng ANDORRA = new LatLng(42.505777, 1.52529);
- private static final LatLng LUXEMBOURG = new LatLng(49.815273, 6.129583);
- private static final LatLng MONACO = new LatLng(43.738418, 7.424616);
- private static final LatLng VATICAN_CITY = new LatLng(41.902916, 12.453389);
- private static final LatLng SAN_MARINO = new LatLng(43.942360, 12.457777);
- private static final LatLng LIECHTENSTEIN = new LatLng(47.166000, 9.555373);
-
- private static final float FULL_ALPHA = 1.0f;
- private static final float PARTIAL_ALPHA = 0.5f;
- private static final float NO_ALPHA = 0.0f;
-
- private List<Polyline> polylines;
- private ArrayList<PolylineOptions> polylineOptions = new ArrayList<>();
- private MapView mapView;
- private MapboxMap mapboxMap;
-
- private boolean fullAlpha = true;
- private boolean visible = true;
- private boolean width = true;
- private boolean color = true;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_polyline);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- if (savedInstanceState != null) {
- polylineOptions = savedInstanceState.getParcelableArrayList(STATE_POLYLINE_OPTIONS);
- } else {
- polylineOptions.addAll(getAllPolylines());
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- PolylineActivity.this.mapboxMap = mapboxMap;
- polylines = mapboxMap.addPolylines(polylineOptions);
- }
- });
-
- View fab = findViewById(R.id.fab);
- if (fab != null) {
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- if (polylines != null && polylines.size() > 0) {
- if (polylines.size() == 1) {
- // test for removing annotation
- mapboxMap.removeAnnotation(polylines.get(0));
- } else {
- // test for removing annotations
- mapboxMap.removeAnnotations(polylines);
- }
- }
- polylineOptions.clear();
- polylineOptions.addAll(getRandomLine());
- polylines = mapboxMap.addPolylines(polylineOptions);
-
- }
- }
- });
- }
+ private static final String STATE_POLYLINE_OPTIONS = "polylineOptions";
+
+ private static final LatLng ANDORRA = new LatLng(42.505777, 1.52529);
+ private static final LatLng LUXEMBOURG = new LatLng(49.815273, 6.129583);
+ private static final LatLng MONACO = new LatLng(43.738418, 7.424616);
+ private static final LatLng VATICAN_CITY = new LatLng(41.902916, 12.453389);
+ private static final LatLng SAN_MARINO = new LatLng(43.942360, 12.457777);
+ private static final LatLng LIECHTENSTEIN = new LatLng(47.166000, 9.555373);
+
+ private static final float FULL_ALPHA = 1.0f;
+ private static final float PARTIAL_ALPHA = 0.5f;
+ private static final float NO_ALPHA = 0.0f;
+
+ private List<Polyline> polylines;
+ private ArrayList<PolylineOptions> polylineOptions = new ArrayList<>();
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+
+ private boolean fullAlpha = true;
+ private boolean visible = true;
+ private boolean width = true;
+ private boolean color = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_polyline);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- private List<PolylineOptions> getAllPolylines() {
- List<PolylineOptions> options = new ArrayList<>();
- options.add(generatePolyline(ANDORRA, LUXEMBOURG, "#F44336"));
- options.add(generatePolyline(ANDORRA, MONACO, "#FF5722"));
- options.add(generatePolyline(MONACO, VATICAN_CITY, "#673AB7"));
- options.add(generatePolyline(VATICAN_CITY, SAN_MARINO, "#009688"));
- options.add(generatePolyline(SAN_MARINO, LIECHTENSTEIN, "#795548"));
- options.add(generatePolyline(LIECHTENSTEIN, LUXEMBOURG, "#3F51B5"));
- return options;
+ if (savedInstanceState != null) {
+ polylineOptions = savedInstanceState.getParcelableArrayList(STATE_POLYLINE_OPTIONS);
+ } else {
+ polylineOptions.addAll(getAllPolylines());
}
- private PolylineOptions generatePolyline(LatLng start, LatLng end, String color) {
- PolylineOptions line = new PolylineOptions();
- line.add(start);
- line.add(end);
- line.color(Color.parseColor(color));
- return line;
- }
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ PolylineActivity.this.mapboxMap = mapboxMap;
+ polylines = mapboxMap.addPolylines(polylineOptions);
+ }
+ });
+
+ View fab = findViewById(R.id.fab);
+ if (fab != null) {
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (mapboxMap != null) {
+ if (polylines != null && polylines.size() > 0) {
+ if (polylines.size() == 1) {
+ // test for removing annotation
+ mapboxMap.removeAnnotation(polylines.get(0));
+ } else {
+ // test for removing annotations
+ mapboxMap.removeAnnotations(polylines);
+ }
+ }
+ polylineOptions.clear();
+ polylineOptions.addAll(getRandomLine());
+ polylines = mapboxMap.addPolylines(polylineOptions);
- public List<PolylineOptions> getRandomLine() {
- final List<PolylineOptions> randomLines = getAllPolylines();
- Collections.shuffle(randomLines);
- return new ArrayList<PolylineOptions>() {{
- add(randomLines.get(0));
+ }
}
- };
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ });
}
+ }
+
+ private List<PolylineOptions> getAllPolylines() {
+ List<PolylineOptions> options = new ArrayList<>();
+ options.add(generatePolyline(ANDORRA, LUXEMBOURG, "#F44336"));
+ options.add(generatePolyline(ANDORRA, MONACO, "#FF5722"));
+ options.add(generatePolyline(MONACO, VATICAN_CITY, "#673AB7"));
+ options.add(generatePolyline(VATICAN_CITY, SAN_MARINO, "#009688"));
+ options.add(generatePolyline(SAN_MARINO, LIECHTENSTEIN, "#795548"));
+ options.add(generatePolyline(LIECHTENSTEIN, LUXEMBOURG, "#3F51B5"));
+ return options;
+ }
+
+ private PolylineOptions generatePolyline(LatLng start, LatLng end, String color) {
+ PolylineOptions line = new PolylineOptions();
+ line.add(start);
+ line.add(end);
+ line.color(Color.parseColor(color));
+ return line;
+ }
+
+ public List<PolylineOptions> getRandomLine() {
+ final List<PolylineOptions> randomLines = getAllPolylines();
+ Collections.shuffle(randomLines);
+ return new ArrayList<PolylineOptions>() {
+ {
+ add(randomLines.get(0));
+ }
+ };
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ outState.putParcelableArrayList(STATE_POLYLINE_OPTIONS, polylineOptions);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_polyline, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_id_remove:
+ // test to remove all annotations
+ polylineOptions.clear();
+ mapboxMap.clear();
+ return true;
+
+ case R.id.action_id_alpha:
+ fullAlpha = !fullAlpha;
+ for (Polyline p : polylines) {
+ p.setAlpha(fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA);
+ }
+ return true;
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- outState.putParcelableArrayList(STATE_POLYLINE_OPTIONS, polylineOptions);
- }
+ case R.id.action_id_color:
+ color = !color;
+ for (Polyline p : polylines) {
+ p.setColor(color ? Color.RED : Color.BLUE);
+ }
+ return true;
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ case R.id.action_id_width:
+ width = !width;
+ for (Polyline p : polylines) {
+ p.setWidth(width ? 3.0f : 5.0f);
+ }
+ return true;
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
+ case R.id.action_id_visible:
+ visible = !visible;
+ for (Polyline p : polylines) {
+ p.setAlpha(visible ? (fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA) : NO_ALPHA);
+ }
+ return true;
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_polyline, menu);
- return super.onCreateOptionsMenu(menu);
- }
+ case android.R.id.home:
+ onBackPressed();
+ return true;
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_id_remove:
- // test to remove all annotations
- polylineOptions.clear();
- mapboxMap.clear();
- return true;
-
- case R.id.action_id_alpha:
- fullAlpha = !fullAlpha;
- for (Polyline p : polylines) {
- p.setAlpha(fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA);
- }
- return true;
-
- case R.id.action_id_color:
- color = !color;
- for (Polyline p : polylines) {
- p.setColor(color ? Color.RED : Color.BLUE);
- }
- return true;
-
- case R.id.action_id_width:
- width = !width;
- for (Polyline p : polylines) {
- p.setWidth(width ? 3.0f : 5.0f);
- }
- return true;
-
- case R.id.action_id_visible:
- visible = !visible;
- for (Polyline p : polylines) {
- p.setAlpha(visible ? (fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA) : NO_ALPHA);
- }
- return true;
-
- case android.R.id.home:
- onBackPressed();
- return true;
-
- default:
- return super.onOptionsItemSelected(item);
- }
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java
index f5030ba649..4b23060eec 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java
@@ -22,118 +22,131 @@ import java.util.ArrayList;
public class PressForMarkerActivity extends AppCompatActivity {
- private MapView mapView;
- private MapboxMap mapboxMap;
- private ArrayList<MarkerOptions> markerList = new ArrayList<>();
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private ArrayList<MarkerOptions> markerList = new ArrayList<>();
- private static final DecimalFormat LAT_LON_FORMATTER = new DecimalFormat("#.#####");
+ private static final DecimalFormat LAT_LON_FORMATTER = new DecimalFormat("#.#####");
- private static String STATE_MARKER_LIST = "markerList";
+ private static String STATE_MARKER_LIST = "markerList";
- @Override
- protected void onCreate(@Nullable final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_press_for_marker);
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_press_for_marker);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(final MapboxMap map) {
- mapboxMap = map;
- resetMap();
-
- mapboxMap.setOnMapLongClickListener(new MapboxMap.OnMapLongClickListener() {
- @Override
- public void onMapLongClick(@NonNull LatLng point) {
- final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
-
- String title = LAT_LON_FORMATTER.format(point.getLatitude()) + ", " + LAT_LON_FORMATTER.format(point.getLongitude());
- String snippet = "X = " + (int) pixel.x + ", Y = " + (int) pixel.y;
-
- MarkerOptions marker = new MarkerOptions()
- .position(point)
- .title(title)
- .snippet(snippet);
-
- markerList.add(marker);
- mapboxMap.addMarker(marker);
- }
- });
-
- if (savedInstanceState != null) {
- markerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST);
- mapboxMap.addMarkers(markerList);
- }
- }
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(final MapboxMap map) {
+ mapboxMap = map;
+ resetMap();
+
+ mapboxMap.setOnMapLongClickListener(new MapboxMap.OnMapLongClickListener() {
+ @Override
+ public void onMapLongClick(@NonNull LatLng point) {
+ final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
+
+ String title = LAT_LON_FORMATTER.format(point.getLatitude()) + ", "
+ + LAT_LON_FORMATTER.format(point.getLongitude());
+ String snippet = "X = " + (int) pixel.x + ", Y = " + (int) pixel.y;
+
+ MarkerOptions marker = new MarkerOptions()
+ .position(point)
+ .title(title)
+ .snippet(snippet);
+
+ markerList.add(marker);
+ mapboxMap.addMarker(marker);
+ }
});
- }
- private void resetMap() {
- if (mapboxMap == null) {
- return;
+ if (savedInstanceState != null) {
+ markerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST);
+ mapboxMap.addMarkers(markerList);
}
- mapboxMap.removeAnnotations();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_press_for_marker, menu);
- return true;
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
-
- mapView.onSaveInstanceState(outState);
- outState.putParcelableArrayList(STATE_MARKER_LIST, markerList);
- }
+ }
+ });
+ }
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
+ private void resetMap() {
+ if (mapboxMap == null) {
+ return;
}
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- case R.id.menuItemReset:
- resetMap();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ mapboxMap.removeAnnotations();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_press_for_marker, menu);
+ return true;
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ mapView.onSaveInstanceState(outState);
+ outState.putParcelableArrayList(STATE_MARKER_LIST, markerList);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.menuItemReset:
+ resetMap();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java
index 91f2a2d69b..3d771613d4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java
@@ -4,199 +4,210 @@ import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
+import timber.log.Timber;
+
public class CameraAnimationTypeActivity extends AppCompatActivity implements OnMapReadyCallback {
- private static final String TAG = "CameraActivity";
- private static final LatLng LAT_LNG_LONDON_EYE = new LatLng(51.50325, -0.11968);
- private static final LatLng LAT_LNG_TOWER_BRIDGE = new LatLng(51.50550, -0.07520);
+ private static final LatLng LAT_LNG_LONDON_EYE = new LatLng(51.50325, -0.11968);
+ private static final LatLng LAT_LNG_TOWER_BRIDGE = new LatLng(51.50550, -0.07520);
- private MapboxMap mapboxMap;
- private MapView mapView;
- private boolean cameraState;
+ private MapboxMap mapboxMap;
+ private MapView mapView;
+ private boolean cameraState;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_camera_animation_types);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_camera_animation_types);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
- mapView = (MapView) findViewById(R.id.mapView);
- if (mapView != null) {
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
+ mapView = (MapView) findViewById(R.id.mapView);
+ if (mapView != null) {
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+ }
+
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ mapboxMap.getUiSettings().setAttributionEnabled(false);
+ mapboxMap.getUiSettings().setLogoEnabled(false);
+ mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
+ @Override
+ public void onCameraChange(CameraPosition position) {
+ Timber.w(position.toString());
+ }
+ });
+
+ // handle move button clicks
+ View moveButton = findViewById(R.id.cameraMoveButton);
+ if (moveButton != null) {
+ moveButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ CameraPosition cameraPosition = new CameraPosition.Builder()
+ .target(getNextLatLng())
+ .zoom(14)
+ .tilt(30)
+ .tilt(0)
+ .build();
+ mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
+ });
}
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- mapboxMap.getUiSettings().setAttributionEnabled(false);
- mapboxMap.getUiSettings().setLogoEnabled(false);
- mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
+ // handle ease button clicks
+ View easeButton = findViewById(R.id.cameraEaseButton);
+ if (easeButton != null) {
+ easeButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ CameraPosition cameraPosition = new CameraPosition.Builder()
+ .target(getNextLatLng())
+ .zoom(15)
+ .bearing(180)
+ .tilt(30)
+ .build();
+
+ MapboxMap.CancelableCallback callback = new MapboxMap.CancelableCallback() {
@Override
- public void onCameraChange(CameraPosition position) {
- Log.v(MapboxConstants.TAG, position.toString());
+ public void onCancel() {
+ Timber.i("Duration onCancel Callback called.");
+ Toast.makeText(
+ CameraAnimationTypeActivity.this,
+ "Ease onCancel Callback called.",
+ Toast.LENGTH_LONG).show();
}
- });
-
- // handle move button clicks
- View moveButton = findViewById(R.id.cameraMoveButton);
- if (moveButton != null) {
- moveButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- CameraPosition cameraPosition = new CameraPosition.Builder()
- .target(getNextLatLng())
- .zoom(14)
- .tilt(30)
- .tilt(0)
- .build();
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
- }
- });
- }
- // handle ease button clicks
- View easeButton = findViewById(R.id.cameraEaseButton);
- if (easeButton != null) {
- easeButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- CameraPosition cameraPosition = new CameraPosition.Builder()
- .target(getNextLatLng())
- .zoom(15)
- .bearing(180)
- .tilt(30)
- .build();
-
- MapboxMap.CancelableCallback callback = new MapboxMap.CancelableCallback() {
- @Override
- public void onCancel() {
- Log.i(TAG, "Duration onCancel Callback called.");
- Toast.makeText(
- CameraAnimationTypeActivity.this,
- "Ease onCancel Callback called.",
- Toast.LENGTH_LONG).show();
- }
-
- @Override
- public void onFinish() {
- Log.i(TAG, "Duration onFinish Callback called.");
- Toast.makeText(
- CameraAnimationTypeActivity.this,
- "Ease onFinish Callback called.",
- Toast.LENGTH_LONG).show();
- }
- };
-
- mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 7500, callback);
- }
- });
- }
+ @Override
+ public void onFinish() {
+ Timber.i("Duration onFinish Callback called.");
+ Toast.makeText(
+ CameraAnimationTypeActivity.this,
+ "Ease onFinish Callback called.",
+ Toast.LENGTH_LONG).show();
+ }
+ };
- // handle animate button clicks
- View animateButton = findViewById(R.id.cameraAnimateButton);
- if (animateButton != null) {
- animateButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- CameraPosition cameraPosition = new CameraPosition.Builder()
- .target(getNextLatLng())
- .bearing(270)
- .tilt(20)
- .build();
-
- MapboxMap.CancelableCallback callback = new MapboxMap.CancelableCallback() {
- @Override
- public void onCancel() {
- Log.i(TAG, "Duration onCancel Callback called.");
- Toast.makeText(
- CameraAnimationTypeActivity.this,
- "Duration onCancel Callback called.",
- Toast.LENGTH_LONG).show();
- }
-
- @Override
- public void onFinish() {
- Log.i(TAG, "Duration onFinish Callback called.");
- Toast.makeText(
- CameraAnimationTypeActivity.this,
- "Duration onFinish Callback called.",
- Toast.LENGTH_LONG).show();
- }
- };
-
- mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 7500, callback);
- }
- });
+ mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 7500, callback);
}
+ });
}
- private LatLng getNextLatLng() {
- cameraState = !cameraState;
- return cameraState ? LAT_LNG_TOWER_BRIDGE : LAT_LNG_LONDON_EYE;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ // handle animate button clicks
+ View animateButton = findViewById(R.id.cameraAnimateButton);
+ if (animateButton != null) {
+ animateButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ CameraPosition cameraPosition = new CameraPosition.Builder()
+ .target(getNextLatLng())
+ .bearing(270)
+ .tilt(20)
+ .build();
+
+ MapboxMap.CancelableCallback callback = new MapboxMap.CancelableCallback() {
+ @Override
+ public void onCancel() {
+ Timber.i("Duration onCancel Callback called.");
+ Toast.makeText(
+ CameraAnimationTypeActivity.this,
+ "Duration onCancel Callback called.",
+ Toast.LENGTH_LONG).show();
+ }
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
+ @Override
+ public void onFinish() {
+ Timber.i("Duration onFinish Callback called.");
+ Toast.makeText(
+ CameraAnimationTypeActivity.this,
+ "Duration onFinish Callback called.",
+ Toast.LENGTH_LONG).show();
+ }
+ };
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 7500, callback);
}
+ });
+ }
+ }
+
+ private LatLng getNextLatLng() {
+ cameraState = !cameraState;
+ return cameraState ? LAT_LNG_TOWER_BRIDGE : LAT_LNG_LONDON_EYE;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
index 925244b4a4..193b59a9db 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
@@ -11,7 +11,9 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
@@ -20,7 +22,6 @@ import android.widget.TextView;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -29,157 +30,188 @@ import com.mapbox.mapboxsdk.testapp.R;
public class CameraPositionActivity extends AppCompatActivity implements OnMapReadyCallback {
- private MapView mapView;
- private MapboxMap mapboxMap;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_camera_position);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
- }
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_camera_position);
- @Override
- public void onMapReady(@NonNull final MapboxMap mapboxMap) {
- this.mapboxMap = mapboxMap;
- // add a listener to FAB
- FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
- fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, R.color.primary));
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Context context = v.getContext();
- final View dialogContent = LayoutInflater.from(context).inflate(R.layout.dialog_camera_position, null);
- AlertDialog.Builder builder = new AlertDialog.Builder(
- context, com.mapbox.mapboxsdk.R.style.AttributionAlertDialogStyle);
- builder.setTitle(R.string.dialog_camera_position);
- builder.setView(onInflateDialogContent(dialogContent));
- builder.setPositiveButton("Animate", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- double latitude = Double.parseDouble(
- ((TextView) dialogContent.findViewById(R.id.value_lat)).getText().toString());
- double longitude = Double.parseDouble(
- ((TextView) dialogContent.findViewById(R.id.value_lon)).getText().toString());
- double zoom = Double.parseDouble(
- ((TextView) dialogContent.findViewById(R.id.value_zoom)).getText().toString());
- double bearing = Double.parseDouble(
- ((TextView) dialogContent.findViewById(R.id.value_bearing)).getText().toString());
- double tilt = Double.parseDouble(
- ((TextView) dialogContent.findViewById(R.id.value_tilt)).getText().toString());
-
- CameraPosition cameraPosition = new CameraPosition.Builder()
- .target(new LatLng(latitude, longitude))
- .zoom(zoom)
- .bearing(bearing)
- .tilt(tilt)
- .build();
-
- mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 5000);
- Log.v(MapboxConstants.TAG, cameraPosition.toString());
- }
- });
- builder.setNegativeButton("Cancel", null);
- builder.setCancelable(false);
- builder.show();
- }
- });
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(@NonNull final MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+
+ mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
+ @Override
+ public void onCameraChange(CameraPosition position) {
+ Timber.w("OnCameraChange: " + position);
+ }
+ });
+
+ // add a listener to FAB
+ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, R.color.primary));
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Context context = view.getContext();
+ final View dialogContent = LayoutInflater.from(context).inflate(R.layout.dialog_camera_position, null);
+ AlertDialog.Builder builder = new AlertDialog.Builder(
+ context, com.mapbox.mapboxsdk.R.style.mapbox_AlertDialogStyle);
+ builder.setTitle(R.string.dialog_camera_position);
+ builder.setView(onInflateDialogContent(dialogContent));
+ builder.setPositiveButton("Animate", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ double latitude = Double.parseDouble(
+ ((TextView) dialogContent.findViewById(R.id.value_lat)).getText().toString());
+ double longitude = Double.parseDouble(
+ ((TextView) dialogContent.findViewById(R.id.value_lon)).getText().toString());
+ double zoom = Double.parseDouble(
+ ((TextView) dialogContent.findViewById(R.id.value_zoom)).getText().toString());
+ double bearing = Double.parseDouble(
+ ((TextView) dialogContent.findViewById(R.id.value_bearing)).getText().toString());
+ double tilt = Double.parseDouble(
+ ((TextView) dialogContent.findViewById(R.id.value_tilt)).getText().toString());
+
+ CameraPosition cameraPosition = new CameraPosition.Builder()
+ .target(new LatLng(latitude, longitude))
+ .zoom(zoom)
+ .bearing(bearing)
+ .tilt(tilt)
+ .build();
+
+ mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 5000,
+ new MapboxMap.CancelableCallback() {
+ @Override
+ public void onCancel() {
+ Timber.v("OnCancel called");
+ }
+
+ @Override
+ public void onFinish() {
+ Timber.v("OnFinish called");
+ }
+ });
+ Timber.v(cameraPosition.toString());
+ }
+ });
+ builder.setNegativeButton("Cancel", null);
+ builder.setCancelable(false);
+ builder.show();
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ }
+
+ private View onInflateDialogContent(View view) {
+ linkTextView(view, R.id.value_lat, R.id.seekbar_lat, new LatLngChangeListener(), 180 + 38);
+ linkTextView(view, R.id.value_lon, R.id.seekbar_lon, new LatLngChangeListener(), 180 - 77);
+ linkTextView(view, R.id.value_zoom, R.id.seekbar_zoom, new ValueChangeListener(), 6);
+ linkTextView(view, R.id.value_bearing, R.id.seekbar_bearing, new ValueChangeListener(), 90);
+ linkTextView(view, R.id.value_tilt, R.id.seekbar_tilt, new ValueChangeListener(), 40);
+ return view;
+ }
+
+ private void linkTextView(
+ View view, @IdRes int textViewRes, @IdRes int seekBarRes, ValueChangeListener listener, int defaultValue) {
+ final TextView value = (TextView) view.findViewById(textViewRes);
+ SeekBar seekBar = (SeekBar) view.findViewById(seekBarRes);
+ listener.setLinkedValueView(value);
+ seekBar.setOnSeekBarChangeListener(listener);
+ seekBar.setProgress(defaultValue);
+ }
+
+ private class ValueChangeListener implements SeekBar.OnSeekBarChangeListener {
+
+ protected TextView textView;
+
+ public void setLinkedValueView(TextView textView) {
+ this.textView = textView;
}
@Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
+ public void onStartTrackingTouch(SeekBar seekBar) {
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
}
- private View onInflateDialogContent(View view) {
- linkTextView(view, R.id.value_lat, R.id.seekbar_lat, new LatLngChangeListener(), 180 + 38);
- linkTextView(view, R.id.value_lon, R.id.seekbar_lon, new LatLngChangeListener(), 180 - 77);
- linkTextView(view, R.id.value_zoom, R.id.seekbar_zoom, new ValueChangeListener(), 6);
- linkTextView(view, R.id.value_bearing, R.id.seekbar_bearing, new ValueChangeListener(), 90);
- linkTextView(view, R.id.value_tilt, R.id.seekbar_tilt, new ValueChangeListener(), 40);
- return view;
- }
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
- private void linkTextView(
- View view, @IdRes int textViewRes, @IdRes int seekBarRes, ValueChangeListener listener, int defaultValue) {
- final TextView value = (TextView) view.findViewById(textViewRes);
- SeekBar seekBar = (SeekBar) view.findViewById(seekBarRes);
- listener.setLinkedValueView(value);
- seekBar.setOnSeekBarChangeListener(listener);
- seekBar.setProgress(defaultValue);
}
- private class ValueChangeListener implements SeekBar.OnSeekBarChangeListener {
-
- protected TextView textView;
-
- public void setLinkedValueView(TextView textView) {
- this.textView = textView;
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
-
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
-
- }
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- textView.setText(String.valueOf(progress));
- }
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ textView.setText(String.valueOf(progress));
}
+ }
- private class LatLngChangeListener extends ValueChangeListener {
+ private class LatLngChangeListener extends ValueChangeListener {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- super.onProgressChanged(seekBar, progress - 180, fromUser);
- }
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ super.onProgressChanged(seekBar, progress - 180, fromUser);
}
-}
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java
index 311991d0d1..3dd6a6344d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java
@@ -4,12 +4,13 @@ import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.MenuItem;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
@@ -24,108 +25,120 @@ import java.util.List;
public class LatLngBoundsActivity extends AppCompatActivity implements OnMapReadyCallback {
- private static final LatLng LOS_ANGELES = new LatLng(34.053940, -118.242622);
- private static final LatLng NEW_YORK = new LatLng(40.712730, -74.005953);
-
- private MapView mapView;
- private MapboxMap mapboxMap;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_visible_bounds);
+ private static final LatLng LOS_ANGELES = new LatLng(34.053940, -118.242622);
+ private static final LatLng NEW_YORK = new LatLng(40.712730, -74.005953);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ private MapView mapView;
+ private MapboxMap mapboxMap;
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.setStyleUrl(Style.DARK);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
- }
-
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- UiSettings uiSettings = mapboxMap.getUiSettings();
- uiSettings.setAllGesturesEnabled(false);
-
- mapboxMap.addMarker(new MarkerOptions()
- .title("Los Angeles")
- .snippet("City Hall")
- .position(LOS_ANGELES));
-
- mapboxMap.addMarker(new MarkerOptions()
- .title("New York")
- .snippet("City Hall")
- .position(NEW_YORK));
-
- List<LatLng> points = new ArrayList<>();
- points.add(NEW_YORK);
- points.add(LOS_ANGELES);
-
- // Create Bounds
- final LatLngBounds bounds = new LatLngBounds.Builder()
- .includes(points)
- .build();
-
- // Add map padding
- int mapPadding = (int) getResources().getDimension(R.dimen.fab_margin);
- mapboxMap.setPadding(mapPadding, mapPadding, mapPadding, mapPadding);
-
- // Move camera to the bounds with added padding
- int padding = (int) getResources().getDimension(R.dimen.coordinatebounds_margin);
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, padding));
-
- // Log data
- Log.e(MapboxConstants.TAG, "Move to bounds: " + bounds.toString());
- Log.e(MapboxConstants.TAG, "Resulting bounds:" + mapboxMap.getProjection().getVisibleRegion().latLngBounds.toString());
- }
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_visible_bounds);
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.setStyleUrl(Style.DARK);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ UiSettings uiSettings = mapboxMap.getUiSettings();
+ uiSettings.setAllGesturesEnabled(false);
+
+ mapboxMap.addMarker(new MarkerOptions()
+ .title("Los Angeles")
+ .snippet("City Hall")
+ .position(LOS_ANGELES));
+
+ mapboxMap.addMarker(new MarkerOptions()
+ .title("New York")
+ .snippet("City Hall")
+ .position(NEW_YORK));
+
+ List<LatLng> points = new ArrayList<>();
+ points.add(NEW_YORK);
+ points.add(LOS_ANGELES);
+
+ // Create Bounds
+ final LatLngBounds bounds = new LatLngBounds.Builder()
+ .includes(points)
+ .build();
+
+ // Add map padding
+ int mapPadding = (int) getResources().getDimension(R.dimen.fab_margin);
+ mapboxMap.setPadding(mapPadding, mapPadding, mapPadding, mapPadding);
+
+ // Move camera to the bounds with added padding
+ int padding = (int) getResources().getDimension(R.dimen.coordinatebounds_margin);
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, padding));
+
+ // Log data
+ Timber.e("Move to bounds: " + bounds.toString());
+ Timber.e("Resulting bounds:" + mapboxMap.getProjection().getVisibleRegion().latLngBounds.toString());
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java
index 740efd5536..4bc30157f8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java
@@ -20,104 +20,116 @@ import com.mapbox.mapboxsdk.testapp.R;
public class ManualZoomActivity extends AppCompatActivity {
- private MapboxMap mapboxMap;
- private MapView mapView;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_manual_zoom);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.setStyleUrl(Style.SATELLITE);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap mapboxMap) {
- ManualZoomActivity.this.mapboxMap = mapboxMap;
-
- UiSettings uiSettings = ManualZoomActivity.this.mapboxMap.getUiSettings();
- uiSettings.setAllGesturesEnabled(false);
- }
- });
- }
+ private MapboxMap mapboxMap;
+ private MapView mapView;
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_zoom, menu);
- return true;
- }
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_manual_zoom);
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
-
- case android.R.id.home:
- onBackPressed();
- return true;
-
- case R.id.action_zoom_in:
- mapboxMap.animateCamera(CameraUpdateFactory.zoomIn());
- return true;
-
- case R.id.action_zoom_out:
- mapboxMap.animateCamera(CameraUpdateFactory.zoomOut());
- return true;
-
- case R.id.action_zoom_by:
- mapboxMap.animateCamera(CameraUpdateFactory.zoomBy(2));
- return true;
- case R.id.action_zoom_to:
- mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(2));
- return true;
-
- case R.id.action_zoom_to_point:
- View view = getWindow().getDecorView();
- mapboxMap.animateCamera(
- CameraUpdateFactory.zoomBy(1, new Point(view.getMeasuredWidth() / 4, view.getMeasuredHeight() / 4)));
- return true;
-
- default:
- return super.onOptionsItemSelected(item);
- }
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.setStyleUrl(Style.SATELLITE);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull final MapboxMap mapboxMap) {
+ ManualZoomActivity.this.mapboxMap = mapboxMap;
+
+ UiSettings uiSettings = ManualZoomActivity.this.mapboxMap.getUiSettings();
+ uiSettings.setAllGesturesEnabled(false);
+ }
+ });
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_zoom, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+
+ case android.R.id.home:
+ onBackPressed();
+ return true;
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
+ case R.id.action_zoom_in:
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomIn());
+ return true;
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ case R.id.action_zoom_out:
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomOut());
+ return true;
+
+ case R.id.action_zoom_by:
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomBy(2));
+ return true;
+ case R.id.action_zoom_to:
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(2));
+ return true;
+
+ case R.id.action_zoom_to_point:
+ View view = getWindow().getDecorView();
+ mapboxMap.animateCamera(
+ CameraUpdateFactory.zoomBy(1, new Point(view.getMeasuredWidth() / 4, view.getMeasuredHeight() / 4)));
+ return true;
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java
index 9fcdfa3880..71e8cc0a08 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java
@@ -13,74 +13,86 @@ import com.mapbox.mapboxsdk.testapp.R;
public class MaxMinZoomActivity extends AppCompatActivity implements OnMapReadyCallback {
- private MapView mapView;
- private MapboxMap mapboxMap;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
- @Override
+ @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_maxmin_zoom);
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_maxmin_zoom);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
- }
-
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- mapboxMap.setMinZoom(3);
- mapboxMap.setMaxZoom(5);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- }
- return false;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ mapboxMap.setMinZoomPreference(3);
+ mapboxMap.setMaxZoomPreference(5);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
}
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
-}
+ return false;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java
index e3dc849ce0..2f16e862ee 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java
@@ -22,127 +22,139 @@ import com.mapbox.mapboxsdk.testapp.R;
public class ScrollByActivity extends AppCompatActivity implements OnMapReadyCallback {
- public static final int MULTIPLIER_PER_PIXEL = 50;
+ public static final int MULTIPLIER_PER_PIXEL = 50;
- private MapView mapView;
- private MapboxMap mapboxMap;
- private SeekBar xBar;
- private SeekBar yBar;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private SeekBar seekBarX;
+ private SeekBar seekBarY;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_scroll_by);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- xBar = (SeekBar) findViewById(R.id.seekbar_move_x);
- TextView xText = (TextView) findViewById(R.id.textview_x);
- xBar.setOnSeekBarChangeListener(new PixelBarChangeListener(xText, R.string.scrollby_x_value));
-
- yBar = (SeekBar) findViewById(R.id.seekbar_move_y);
- TextView yText = (TextView) findViewById(R.id.textview_y);
- yBar.setOnSeekBarChangeListener(new PixelBarChangeListener(yText, R.string.scrollby_y_value));
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.setTag(true);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
- }
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_scroll_by);
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- UiSettings uiSettings = mapboxMap.getUiSettings();
- uiSettings.setLogoEnabled(false);
- uiSettings.setAttributionEnabled(false);
-
- FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
- fab.setColorFilter(ContextCompat.getColor(ScrollByActivity.this, R.color.primary));
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- mapboxMap.easeCamera(CameraUpdateFactory.scrollBy(
- xBar.getProgress() * MULTIPLIER_PER_PIXEL,
- yBar.getProgress() * MULTIPLIER_PER_PIXEL)
- );
- }
- });
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ seekBarX = (SeekBar) findViewById(R.id.seekbar_move_x);
+ TextView textViewX = (TextView) findViewById(R.id.textview_x);
+ seekBarX.setOnSeekBarChangeListener(new PixelBarChangeListener(textViewX, R.string.scrollby_x_value));
+
+ seekBarY = (SeekBar) findViewById(R.id.seekbar_move_y);
+ TextView textViewY = (TextView) findViewById(R.id.textview_y);
+ seekBarY.setOnSeekBarChangeListener(new PixelBarChangeListener(textViewY, R.string.scrollby_y_value));
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.setTag(true);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ UiSettings uiSettings = mapboxMap.getUiSettings();
+ uiSettings.setLogoEnabled(false);
+ uiSettings.setAttributionEnabled(false);
+
+ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setColorFilter(ContextCompat.getColor(ScrollByActivity.this, R.color.primary));
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ mapboxMap.easeCamera(CameraUpdateFactory.scrollBy(
+ seekBarX.getProgress() * MULTIPLIER_PER_PIXEL,
+ seekBarY.getProgress() * MULTIPLIER_PER_PIXEL)
+ );
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
+ private static class PixelBarChangeListener implements SeekBar.OnSeekBarChangeListener {
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ @StringRes
+ private int prefixTextResource;
+ private TextView valueView;
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ public PixelBarChangeListener(@NonNull TextView textView, @StringRes int textRes) {
+ valueView = textView;
+ prefixTextResource = textRes;
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ int value = progress * ScrollByActivity.MULTIPLIER_PER_PIXEL;
+ valueView.setText(String.format(seekBar.getResources().getString(prefixTextResource), value));
}
- private static class PixelBarChangeListener implements SeekBar.OnSeekBarChangeListener {
-
- @StringRes
- private int prefixTextResource;
- private TextView valueView;
-
- public PixelBarChangeListener(@NonNull TextView textView, @StringRes int textRes) {
- valueView = textView;
- prefixTextResource = textRes;
- }
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- int value = progress * ScrollByActivity.MULTIPLIER_PER_PIXEL;
- valueView.setText(String.format(seekBar.getResources().getString(prefixTextResource), value));
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
- }
+ }
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
- }
}
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java
index a1aced6eaa..8e4b58366f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java
@@ -6,7 +6,9 @@ import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -22,131 +24,148 @@ import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.model.customlayer.ExampleCustomLayer;
public class CustomLayerActivity extends AppCompatActivity {
- private static final String TAG = CustomLayerActivity.class.getSimpleName();
-
- private MapboxMap mapboxMap;
- private MapView mapView;
-
- private boolean isShowingCustomLayer = false;
- private FloatingActionButton fab;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_custom_layer);
-
- setupActionBar();
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
-
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(39.91448, -243.60947), 10));
-
- }
- });
-
- fab = (FloatingActionButton) findViewById(R.id.fab);
- fab.setColorFilter(ContextCompat.getColor(this, R.color.primary));
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- swapCustomLayer();
- }
- }
- });
- }
-
- private void swapCustomLayer() {
-
- if (isShowingCustomLayer) {
- try {
- mapboxMap.removeLayer("custom");
- } catch (NoSuchLayerException noSuchLayerException) {
- Log.e(TAG, "No custom layer to remove");
- }
- fab.setImageResource(R.drawable.ic_layers_24dp);
- } else {
- mapboxMap.addLayer(new CustomLayer("custom",
- ExampleCustomLayer.createContext(),
- ExampleCustomLayer.InitializeFunction,
- ExampleCustomLayer.RenderFunction,
- ExampleCustomLayer.DeinitializeFunction), "building");
- fab.setImageResource(R.drawable.ic_layers_clear_24dp);
- }
-
- isShowingCustomLayer = !isShowingCustomLayer;
- }
- private void updateLayer() {
- CustomLayer custom = mapboxMap.getLayerAs("custom");
- if (custom != null) {
- custom.update();
+ private MapboxMap mapboxMap;
+ private MapView mapView;
+ private CustomLayer customLayer;
+
+ private FloatingActionButton fab;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_custom_layer);
+
+ setupActionBar();
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(39.91448, -243.60947), 10));
+
+ }
+ });
+
+ fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setColorFilter(ContextCompat.getColor(this, R.color.primary));
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (mapboxMap != null) {
+ swapCustomLayer();
}
+ }
+ });
+ }
+
+ private void swapCustomLayer() {
+ if (customLayer != null) {
+ try {
+ mapboxMap.removeLayer(customLayer.getId());
+ customLayer = null;
+ } catch (NoSuchLayerException noSuchLayerException) {
+ Timber.e("No custom layer to remove");
+ }
+ fab.setImageResource(R.drawable.ic_layers_24dp);
+ } else {
+ customLayer = new CustomLayer("custom",
+ ExampleCustomLayer.createContext(),
+ ExampleCustomLayer.InitializeFunction,
+ ExampleCustomLayer.RenderFunction,
+ ExampleCustomLayer.DeinitializeFunction);
+ mapboxMap.addLayer(customLayer, "building");
+ fab.setImageResource(R.drawable.ic_layers_clear_24dp);
}
+ }
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ private void updateLayer() {
+ if (customLayer != null) {
+ customLayer.update();
}
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_custom_layer, menu);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_custom_layer, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
return true;
+ case R.id.action_update_layer:
+ updateLayer();
+ return true;
+ case R.id.action_set_color_red:
+ ExampleCustomLayer.setColor(1, 0, 0, 1);
+ return true;
+ case R.id.action_set_color_green:
+ ExampleCustomLayer.setColor(0, 1, 0, 1);
+ return true;
+ case R.id.action_set_color_blue:
+ ExampleCustomLayer.setColor(0, 0, 1, 1);
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- case R.id.action_update_layer:
- updateLayer();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- private void setupActionBar() {
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ private void setupActionBar() {
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/directions/DirectionsActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/directions/DirectionsActivity.java
index 6d5d63dbf7..13e384a8b5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/directions/DirectionsActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/directions/DirectionsActivity.java
@@ -6,8 +6,11 @@ import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.MenuItem;
+
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.annotations.PolylineOptions;
import com.mapbox.mapboxsdk.camera.CameraPosition;
@@ -18,172 +21,193 @@ import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.services.Constants;
-import com.mapbox.services.commons.ServicesException;
+import com.mapbox.services.api.ServicesException;
import com.mapbox.services.commons.geojson.LineString;
import com.mapbox.services.commons.models.Position;
-import com.mapbox.services.directions.v4.DirectionsCriteria;
-import com.mapbox.services.directions.v4.MapboxDirections;
-import com.mapbox.services.directions.v4.models.DirectionsResponse;
-import com.mapbox.services.directions.v4.models.DirectionsRoute;
-import com.mapbox.services.directions.v4.models.Waypoint;
+import com.mapbox.services.api.directions.v5.DirectionsCriteria;
+import com.mapbox.services.api.directions.v5.MapboxDirections;
+import com.mapbox.services.api.directions.v5.models.DirectionsResponse;
+import com.mapbox.services.api.directions.v5.models.DirectionsRoute;
+
+import java.util.ArrayList;
+import java.util.List;
+
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class DirectionsActivity extends AppCompatActivity {
- private static final String LOG_TAG = "DirectionsActivity";
-
- private MapView mapView;
- private MapboxMap mapboxMap;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_directions);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- DirectionsActivity.this.mapboxMap = mapboxMap;
- loadRoute();
- }
- });
- }
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_directions);
- private void loadRoute() {
- // Dupont Circle (Washington, DC)
- Waypoint origin = new Waypoint(-77.04341, 38.90962);
-
- // The White House (Washington, DC)
- Waypoint destination = new Waypoint(-77.0365, 38.8977);
-
- // Set map at centroid
- LatLng centroid = new LatLng(
- (origin.getLatitude() + destination.getLatitude()) / 2,
- (origin.getLongitude() + destination.getLongitude()) / 2);
-
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
- .target(centroid)
- .zoom(14)
- .build()));
-
- // Add origin and destination to the map
- mapboxMap.addMarker(new MarkerOptions()
- .position(new LatLng(origin.getLatitude(), origin.getLongitude()))
- .title("Origin")
- .snippet("Dupont Circle"));
- mapboxMap.addMarker(new MarkerOptions()
- .position(new LatLng(destination.getLatitude(), destination.getLongitude()))
- .title("Destination")
- .snippet("The White House"));
-
- // Get route from API
- getRoute(origin, destination);
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- private void getRoute(Waypoint origin, Waypoint destination) {
- try {
- MapboxDirections md = new MapboxDirections.Builder()
- .setAccessToken(getString(R.string.mapbox_access_token))
- .setOrigin(origin)
- .setDestination(destination)
- .setProfile(DirectionsCriteria.PROFILE_WALKING)
- .build();
-
- md.enqueueCall(new Callback<DirectionsResponse>() {
-
- @Override
- public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
- Log.e(LOG_TAG, "Error: " + throwable.getMessage());
- }
-
- @Override
- public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
- // You can get generic HTTP info about the response
- Log.d(LOG_TAG, "Response code: " + response.code());
-
- // Print some info about the route
- DirectionsRoute currentRoute = response.body().getRoutes().get(0);
- Log.d(LOG_TAG, "Distance: " + currentRoute.getDistance());
-
- // Draw the route on the map
- drawRoute(currentRoute);
- }
-
- });
- } catch (ServicesException servicesException) {
- Log.e(LOG_TAG, "Error displaying route: " + servicesException.toString());
- servicesException.printStackTrace();
- }
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- private void drawRoute(DirectionsRoute route) {
-
- PolylineOptions builder = new PolylineOptions();
- builder.color(Color.parseColor("#3887be"));
- builder.alpha(0.5f);
- builder.width(5);
- builder.width(5);
- LineString lineString = route.asLineString(Constants.OSRM_PRECISION_V4);
- for (Position coordinates : lineString.getCoordinates()) {
- builder.add(new LatLng(coordinates.getLatitude(), coordinates.getLongitude()));
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ DirectionsActivity.this.mapboxMap = mapboxMap;
+ loadRoute();
+ }
+ });
+ }
+
+ private void loadRoute() {
+ // Dupont Circle (Washington, DC)
+ Position origin = Position.fromCoordinates(-77.04341, 38.90962);
+
+ // The White House (Washington, DC)
+ Position destination = Position.fromCoordinates(-77.0365, 38.8977);
+
+ // Set map at centroid
+ LatLng centroid = new LatLng(
+ (origin.getLatitude() + destination.getLatitude()) / 2,
+ (origin.getLongitude() + destination.getLongitude()) / 2);
+
+ mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
+ .target(centroid)
+ .zoom(14)
+ .build()));
+
+ // Add origin and destination to the map
+ mapboxMap.addMarker(new MarkerOptions()
+ .position(new LatLng(origin.getLatitude(), origin.getLongitude()))
+ .title("Origin")
+ .snippet("Dupont Circle"));
+ mapboxMap.addMarker(new MarkerOptions()
+ .position(new LatLng(destination.getLatitude(), destination.getLongitude()))
+ .title("Destination")
+ .snippet("The White House"));
+
+ // Get route from API
+ getRoute(origin, destination);
+ }
+
+ private void getRoute(Position origin, Position destination) {
+ try {
+ MapboxDirections md = new MapboxDirections.Builder()
+ .setAccessToken(getString(R.string.mapbox_access_token))
+ .setOrigin(origin)
+ .setOverview(DirectionsCriteria.OVERVIEW_FULL)
+ .setDestination(destination)
+ .setProfile(DirectionsCriteria.PROFILE_WALKING)
+ .build();
+
+ md.enqueueCall(new Callback<DirectionsResponse>() {
+
+ @Override
+ public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
+ Timber.e("Error: " + throwable.getMessage());
}
- // Draw Points on MapView
- mapboxMap.addPolyline(builder);
- }
+ @Override
+ public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
+ // You can get generic HTTP info about the response
+ Timber.d("Response code: " + response.code());
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
+ // Print some info about the route
+ DirectionsRoute currentRoute = response.body().getRoutes().get(0);
+ Timber.d("Distance: " + currentRoute.getDistance());
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
+ // Draw the route on the map
+ drawRoute(currentRoute);
+ }
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ });
+ } catch (ServicesException servicesException) {
+ Timber.e("Error displaying route: " + servicesException.toString());
+ servicesException.printStackTrace();
}
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ }
+
+ private void drawRoute(DirectionsRoute route) {
+
+ PolylineOptions builder = new PolylineOptions();
+ builder.color(Color.parseColor("#3887be"));
+ builder.alpha(0.5f);
+ builder.width(5);
+ builder.width(5);
+
+ LineString lineString = LineString.fromPolyline(route.getGeometry(), Constants.OSRM_PRECISION_V5);
+ List<Position> coordinates = lineString.getCoordinates();
+ List<LatLng> points = new ArrayList<>();
+ for (int i = 0; i < coordinates.size(); i++) {
+ points.add(new LatLng(
+ coordinates.get(i).getLatitude(),
+ coordinates.get(i).getLongitude()));
}
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ builder.addAll(points);
+
+ // Draw Points on MapView
+ mapboxMap.addPolyline(builder);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/espresso/EspressoTestActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/espresso/EspressoTestActivity.java
new file mode 100644
index 0000000000..677e09e719
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/espresso/EspressoTestActivity.java
@@ -0,0 +1,80 @@
+package com.mapbox.mapboxsdk.testapp.activity.espresso;
+
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.testapp.R;
+
+/**
+ * Base activity for instrumentation testing
+ */
+public class EspressoTestActivity extends AppCompatActivity implements OnMapReadyCallback {
+
+ public MapView mapView;
+ protected MapboxMap mapboxMap;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_camera_test);
+
+ //Initialize map as normal
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ }
+
+ public MapboxMap getMapboxMap() {
+ return mapboxMap;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java
index f9a067daf0..00cc8dfac7 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java
@@ -5,15 +5,11 @@ import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.google.gson.JsonElement;
-import com.mapbox.mapboxsdk.annotations.Marker;
-import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
@@ -23,137 +19,143 @@ import com.mapbox.services.commons.geojson.Feature;
import java.util.List;
import java.util.Map;
+import timber.log.Timber;
+
/**
* Demo's query rendered features
*/
public class QueryRenderedFeaturesBoxCountActivity extends AppCompatActivity {
- private static final String TAG = QueryRenderedFeaturesBoxCountActivity.class.getSimpleName();
-
- public MapView mapView;
- private MapboxMap mapboxMap;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_query_features_box);
- setupActionBar();
-
- final float density = getResources().getDisplayMetrics().density;
-
- final View selectionBox = findViewById(R.id.selection_box);
-
- //Initialize map as normal
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @SuppressWarnings("ConstantConditions")
- @Override
- public void onMapReady(final MapboxMap mapboxMap) {
- QueryRenderedFeaturesBoxCountActivity.this.mapboxMap = mapboxMap;
-
-
- selectionBox.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- //Query
- int top = selectionBox.getTop() - mapView.getTop();
- int left = selectionBox.getLeft() - mapView.getLeft();
- RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
- Log.i(TAG, String.format("Querying box %s", box));
- List<Feature> features = mapboxMap.queryRenderedFeatures(box);
-
- //Show count
- Toast.makeText(
- QueryRenderedFeaturesBoxCountActivity.this,
- String.format("%s features in box", features.size()),
- Toast.LENGTH_SHORT).show();
-
- //Debug output
- debugOutput(features);
- }
- });
-
- //Little taste of home
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.0907, 5.1214), 16));
- }
- });
- }
-
- private void debugOutput(List<Feature> features) {
- Log.i(TAG, String.format("Got %s features", features.size()));
- for (Feature feature : features) {
- if (feature != null) {
- Log.i(TAG, String.format("Got feature %s with %s properties and Geometry %s",
- feature.getId(),
- feature.getProperties() != null ? feature.getProperties().entrySet().size() : "<null>",
- feature.getGeometry() != null ? feature.getGeometry().getClass().getSimpleName() : "<null>")
- );
- if (feature.getProperties() != null) {
- for (Map.Entry<String, JsonElement> entry : feature.getProperties().entrySet()) {
- Log.i(TAG, String.format("Prop %s - %s", entry.getKey(), entry.getValue()));
- }
- }
- } else {
- Log.i(TAG, "Got NULL feature %s");
- }
+ public MapView mapView;
+ private MapboxMap mapboxMap;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_query_features_box);
+ setupActionBar();
+
+ final View selectionBox = findViewById(R.id.selection_box);
+
+ //Initialize map as normal
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @SuppressWarnings("ConstantConditions")
+ @Override
+ public void onMapReady(final MapboxMap mapboxMap) {
+ QueryRenderedFeaturesBoxCountActivity.this.mapboxMap = mapboxMap;
+ selectionBox.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ //Query
+ int top = selectionBox.getTop() - mapView.getTop();
+ int left = selectionBox.getLeft() - mapView.getLeft();
+ RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
+ Timber.i(String.format("Querying box %s", box));
+ List<Feature> features = mapboxMap.queryRenderedFeatures(box);
+
+ //Show count
+ Toast.makeText(
+ QueryRenderedFeaturesBoxCountActivity.this,
+ String.format("%s features in box", features.size()),
+ Toast.LENGTH_SHORT).show();
+
+ //Debug output
+ debugOutput(features);
+ }
+ });
+ }
+ });
+ }
+
+ private void debugOutput(List<Feature> features) {
+ Timber.i(String.format("Got %s features", features.size()));
+ for (Feature feature : features) {
+ if (feature != null) {
+ Timber.i(String.format("Got feature %s with %s properties and Geometry %s",
+ feature.getId(),
+ feature.getProperties() != null ? feature.getProperties().entrySet().size() : "<null>",
+ feature.getGeometry() != null ? feature.getGeometry().getClass().getSimpleName() : "<null>")
+ );
+ if (feature.getProperties() != null) {
+ for (Map.Entry<String, JsonElement> entry : feature.getProperties().entrySet()) {
+ Timber.i(String.format("Prop %s - %s", entry.getKey(), entry.getValue()));
+ }
}
+ } else {
+ // TODO Question: Why not formatting here??
+ Timber.i("Got NULL feature %s");
+ }
}
-
- public MapboxMap getMapboxMap() {
- return mapboxMap;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ }
+
+ public MapboxMap getMapboxMap() {
+ return mapboxMap;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
+ private void setupActionBar() {
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- private void setupActionBar() {
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java
index 1e8f91857b..8c4a499f9b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java
@@ -6,14 +6,10 @@ import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
-import com.mapbox.mapboxsdk.annotations.Marker;
-import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
@@ -25,128 +21,138 @@ import com.mapbox.services.commons.geojson.FeatureCollection;
import java.util.List;
+import timber.log.Timber;
+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillColor;
/**
* Demo's query rendered features
*/
public class QueryRenderedFeaturesBoxHighlightActivity extends AppCompatActivity {
- private static final String TAG = QueryRenderedFeaturesBoxHighlightActivity.class.getSimpleName();
-
- public MapView mapView;
- private MapboxMap mapboxMap;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_query_features_box);
- setupActionBar();
-
- final View selectionBox = findViewById(R.id.selection_box);
-
- //Initialize map as normal
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @SuppressWarnings("ConstantConditions")
- @Override
- public void onMapReady(final MapboxMap mapboxMap) {
- QueryRenderedFeaturesBoxHighlightActivity.this.mapboxMap = mapboxMap;
-
- //Add a fill layer to display stuff on
-
- selectionBox.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- //Query
- int top = selectionBox.getTop() - mapView.getTop();
- int left = selectionBox.getLeft() - mapView.getLeft();
- RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
- Log.i(TAG, String.format("Querying box %s for buildings", box));
- List<Feature> features = mapboxMap.queryRenderedFeatures(box, "building");
-
- //Show count
- Toast.makeText(
- QueryRenderedFeaturesBoxHighlightActivity.this,
- String.format("%s features in box", features.size()),
- Toast.LENGTH_SHORT).show();
-
- //remove layer / source if already added
- try {
- mapboxMap.removeSource("highlighted-shapes-source");
- mapboxMap.removeLayer("highlighted-shapes-layer");
- } catch (Exception exception) {
- //that's ok
- }
-
- //Add layer / source
- mapboxMap.addSource(new GeoJsonSource("highlighted-shapes-source", FeatureCollection.fromFeatures(features)));
- mapboxMap.addLayer(new FillLayer("highlighted-shapes-layer", "highlighted-shapes-source")
- .withProperties(fillColor(Color.RED)));
- }
- });
-
- //Little taste of home
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.0907, 5.1214), 16));
- }
- });
-
- }
-
- public MapboxMap getMapboxMap() {
- return mapboxMap;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
+ public MapView mapView;
+ private MapboxMap mapboxMap;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_query_features_box);
+ setupActionBar();
+
+ final View selectionBox = findViewById(R.id.selection_box);
+
+ //Initialize map as normal
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @SuppressWarnings("ConstantConditions")
+ @Override
+ public void onMapReady(final MapboxMap mapboxMap) {
+ QueryRenderedFeaturesBoxHighlightActivity.this.mapboxMap = mapboxMap;
+ selectionBox.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ //Query
+ int top = selectionBox.getTop() - mapView.getTop();
+ int left = selectionBox.getLeft() - mapView.getLeft();
+ RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
+ Timber.i(String.format("Querying box %s for buildings", box));
+ List<Feature> features = mapboxMap.queryRenderedFeatures(box, "building");
+
+ //Show count
+ Toast.makeText(
+ QueryRenderedFeaturesBoxHighlightActivity.this,
+ String.format("%s features in box", features.size()),
+ Toast.LENGTH_SHORT).show();
+
+ //remove layer / source if already added
+ try {
+ mapboxMap.removeSource("highlighted-shapes-source");
+ mapboxMap.removeLayer("highlighted-shapes-layer");
+ } catch (Exception exception) {
+ //that's ok
+ }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ //Add layer / source
+ mapboxMap.addSource(
+ new GeoJsonSource("highlighted-shapes-source",
+ FeatureCollection.fromFeatures(features))
+ );
+ mapboxMap.addLayer(new FillLayer("highlighted-shapes-layer", "highlighted-shapes-source")
+ .withProperties(fillColor(Color.RED)));
+ }
+ });
+ }
+ });
+
+ }
+
+ public MapboxMap getMapboxMap() {
+ return mapboxMap;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
- private void setupActionBar() {
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ private void setupActionBar() {
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java
new file mode 100644
index 0000000000..4b7bbb9614
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java
@@ -0,0 +1,186 @@
+package com.mapbox.mapboxsdk.testapp.activity.feature;
+
+import android.graphics.BitmapFactory;
+import android.graphics.RectF;
+import android.os.Bundle;
+import android.support.annotation.RawRes;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Toast;
+
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
+import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.services.commons.geojson.Feature;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.List;
+
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
+
+/**
+ * Demo's query rendered features on Symbols
+ */
+public class QueryRenderedFeaturesBoxSymbolCountActivity extends AppCompatActivity {
+
+ public MapView mapView;
+ private MapboxMap mapboxMap;
+
+ private Toast toast;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_query_features_box);
+ setupActionBar();
+
+ final View selectionBox = findViewById(R.id.selection_box);
+
+ //Initialize map as normal
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @SuppressWarnings("ConstantConditions")
+ @Override
+ public void onMapReady(final MapboxMap mapboxMap) {
+ QueryRenderedFeaturesBoxSymbolCountActivity.this.mapboxMap = mapboxMap;
+
+ //Add a symbol layer (also works with annotations)
+ try {
+ mapboxMap.addSource(new GeoJsonSource("symbols-source", readRawResource(R.raw.test_points_utrecht)));
+ } catch (IOException ioException) {
+ Timber.e("Could not load geojson: " + ioException.getMessage());
+ return;
+ }
+ mapboxMap.addImage(
+ "test-icon",
+ BitmapFactory.decodeResource(getResources(),
+ R.drawable.mapbox_marker_icon_default)
+ );
+ mapboxMap.addLayer(new SymbolLayer("symbols-layer", "symbols-source").withProperties(iconImage("test-icon")));
+
+ selectionBox.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ //Query
+ int top = selectionBox.getTop() - mapView.getTop();
+ int left = selectionBox.getLeft() - mapView.getLeft();
+ RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
+ Timber.i(String.format("Querying box %s", box));
+ List<Feature> features = mapboxMap.queryRenderedFeatures(box, "symbols-layer");
+
+ //Show count
+ if (toast != null) {
+ toast.cancel();
+ }
+ toast = Toast.makeText(
+ QueryRenderedFeaturesBoxSymbolCountActivity.this,
+ String.format("%s features in box", features.size()),
+ Toast.LENGTH_SHORT);
+ toast.show();
+ }
+ });
+ }
+ });
+ }
+
+ private String readRawResource(@RawRes int rawResource) throws IOException {
+ InputStream is = getResources().openRawResource(rawResource);
+ Writer writer = new StringWriter();
+ char[] buffer = new char[1024];
+ try {
+ Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+ int numRead;
+ while ((numRead = reader.read(buffer)) != -1) {
+ writer.write(buffer, 0, numRead);
+ }
+ } finally {
+ is.close();
+ }
+
+ return writer.toString();
+ }
+
+ public MapboxMap getMapboxMap() {
+ return mapboxMap;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private void setupActionBar() {
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+ }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java
index 8abf638d16..17dfbc18b4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java
@@ -9,7 +9,9 @@ import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
@@ -18,7 +20,6 @@ import android.widget.TextView;
import com.google.gson.JsonElement;
import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
import com.mapbox.mapboxsdk.annotations.Marker;
-import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -33,229 +34,236 @@ import java.util.Map;
* Demo's query rendered features
*/
public class QueryRenderedFeaturesPropertiesActivity extends AppCompatActivity {
- private static final String TAG = QueryRenderedFeaturesPropertiesActivity.class.getSimpleName();
- public MapView mapView;
- private MapboxMap mapboxMap;
- private Marker marker;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_query_features_point);
- setupActionBar();
-
- final float density = getResources().getDisplayMetrics().density;
-
- //Initialize map as normal
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(final MapboxMap mapboxMap) {
- QueryRenderedFeaturesPropertiesActivity.this.mapboxMap = mapboxMap;
-
- //Add custom window adapter
- addCustomInfoWindowAdapter(mapboxMap);
-
- //Add a click listener
- mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- //Query
- final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
- Log.i(TAG, String.format(
- "Requesting features for %sx%s (%sx%s adjusted for density)",
- pixel.x, pixel.y, pixel.x / density, pixel.y / density)
- );
- List<Feature> features = mapboxMap.queryRenderedFeatures(pixel);
-
- //Debug output
- debugOutput(features);
-
- //Remove any previous markers
- if (marker != null) {
- mapboxMap.removeMarker(marker);
- }
-
- //Add a marker on the clicked point
- marker = mapboxMap.addMarker(new CustomMarkerOptions().position(point).features(features));
- mapboxMap.selectMarker(marker);
- }
- });
-
- //Little taste of home
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.0907, 5.1214), 16));
+ public MapView mapView;
+ private MapboxMap mapboxMap;
+ private Marker marker;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_query_features_point);
+ setupActionBar();
+
+ final float density = getResources().getDisplayMetrics().density;
+
+ //Initialize map as normal
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(final MapboxMap mapboxMap) {
+ QueryRenderedFeaturesPropertiesActivity.this.mapboxMap = mapboxMap;
+
+ //Add custom window adapter
+ addCustomInfoWindowAdapter(mapboxMap);
+
+ //Add a click listener
+ mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
+ @Override
+ public void onMapClick(@NonNull LatLng point) {
+ //Query
+ final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
+ Timber.i(String.format(
+ "Requesting features for %sx%s (%sx%s adjusted for density)",
+ pixel.x, pixel.y, pixel.x / density, pixel.y / density)
+ );
+ List<Feature> features = mapboxMap.queryRenderedFeatures(pixel);
+
+ //Debug output
+ debugOutput(features);
+
+ //Remove any previous markers
+ if (marker != null) {
+ mapboxMap.removeMarker(marker);
}
+
+ //Add a marker on the clicked point
+ marker = mapboxMap.addMarker(new CustomMarkerOptions().position(point).features(features));
+ mapboxMap.selectMarker(marker);
+ }
});
+ }
+ });
+
+ }
+
+ private void debugOutput(List<Feature> features) {
+ Timber.i(String.format("Got %s features", features.size()));
+ for (Feature feature : features) {
+ if (feature != null) {
+ Timber.i(String.format("Got feature %s with %s properties and Geometry %s",
+ feature.getId(),
+ feature.getProperties() != null ? feature.getProperties().entrySet().size() : "<null>",
+ feature.getGeometry() != null ? feature.getGeometry().getClass().getSimpleName() : "<null>")
+ );
+ if (feature.getProperties() != null) {
+ for (Map.Entry<String, JsonElement> entry : feature.getProperties().entrySet()) {
+ Timber.i(String.format("Prop %s - %s", entry.getKey(), entry.getValue()));
+ }
+ }
+ } else {
+ // TODO Question: Why not formatting here??
+ Timber.i("Got NULL feature %s");
+ }
+ }
+ }
+
+ private void addCustomInfoWindowAdapter(MapboxMap mapboxMap) {
+ mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
+
+ private TextView row(String text) {
+ TextView view = new TextView(QueryRenderedFeaturesPropertiesActivity.this);
+ view.setText(text);
+ return view;
+ }
+
+ @Override
+ public View getInfoWindow(@NonNull Marker marker) {
+ CustomMarker customMarker = (CustomMarker) marker;
+ LinearLayout view = new LinearLayout(QueryRenderedFeaturesPropertiesActivity.this);
+ view.setOrientation(LinearLayout.VERTICAL);
+ view.setBackgroundColor(Color.WHITE);
+
+ if (customMarker.features.size() > 0) {
+ view.addView(row(String.format("Found %s features", customMarker.features.size())));
+ Feature feature = customMarker.features.get(0);
+ for (Map.Entry<String, JsonElement> prop : feature.getProperties().entrySet()) {
+ view.addView(row(String.format("%s: %s", prop.getKey(), prop.getValue())));
+ }
+ } else {
+ view.addView(row("No features here"));
+ }
+ return view;
+ }
+ });
+ }
+
+ public MapboxMap getMapboxMap() {
+ return mapboxMap;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
- private void debugOutput(List<Feature> features) {
- Log.i(TAG, String.format("Got %s features", features.size()));
- for (Feature feature : features) {
- if (feature != null) {
- Log.i(TAG, String.format("Got feature %s with %s properties and Geometry %s",
- feature.getId(),
- feature.getProperties() != null ? feature.getProperties().entrySet().size() : "<null>",
- feature.getGeometry() != null ? feature.getGeometry().getClass().getSimpleName() : "<null>")
- );
- if (feature.getProperties() != null) {
- for (Map.Entry<String, JsonElement> entry : feature.getProperties().entrySet()) {
- Log.i(TAG, String.format("Prop %s - %s", entry.getKey(), entry.getValue()));
- }
- }
- } else {
- Log.i(TAG, "Got NULL feature %s");
- }
- }
+ private void setupActionBar() {
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
+ }
- private void addCustomInfoWindowAdapter(MapboxMap mapboxMap) {
- mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
+ private static class CustomMarker extends Marker {
- private TextView row(String text) {
- TextView view = new TextView(QueryRenderedFeaturesPropertiesActivity.this);
- view.setText(text);
- return view;
- }
+ private final List<Feature> features;
- private int tenDp = (int) getResources().getDimension(R.dimen.attr_margin);
-
- @Override
- public View getInfoWindow(@NonNull Marker marker) {
- CustomMarker customMarker = (CustomMarker) marker;
- LinearLayout view = new LinearLayout(QueryRenderedFeaturesPropertiesActivity.this);
- view.setOrientation(LinearLayout.VERTICAL);
- view.setBackgroundColor(Color.WHITE);
-
- if (customMarker.features.size() > 0) {
- view.addView(row(String.format("Found %s features", customMarker.features.size())));
- Feature feature = customMarker.features.get(0);
- for (Map.Entry<String, JsonElement> prop : feature.getProperties().entrySet()) {
- view.addView(row(String.format("%s: %s", prop.getKey(), prop.getValue())));
- }
- } else {
- view.addView(row("No features here"));
- }
-
- return view;
- }
- });
+ public CustomMarker(BaseMarkerOptions baseMarkerOptions, List<Feature> features) {
+ super(baseMarkerOptions);
+ this.features = features;
}
+ }
- public MapboxMap getMapboxMap() {
- return mapboxMap;
- }
+ private static class CustomMarkerOptions extends BaseMarkerOptions<CustomMarker, CustomMarkerOptions> {
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
+ private List<Feature> features;
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ public CustomMarkerOptions features(List<Feature> features) {
+ this.features = features;
+ return this;
}
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ public CustomMarkerOptions() {
}
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ private CustomMarkerOptions(Parcel in) {
+ //Should implement this
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ public CustomMarkerOptions getThis() {
+ return this;
}
- private void setupActionBar() {
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
- }
-
- private static class CustomMarker extends Marker {
-
- private final List<Feature> features;
-
- public CustomMarker(BaseMarkerOptions baseMarkerOptions, List<Feature> features) {
- super(baseMarkerOptions);
- this.features = features;
- }
+ @Override
+ public CustomMarker getMarker() {
+ return new CustomMarker(this, features);
}
- private static class CustomMarkerOptions extends BaseMarkerOptions<CustomMarker, CustomMarkerOptions> {
-
-
- private List<Feature> features;
-
- public CustomMarkerOptions features(List<Feature> features) {
- this.features = features;
- return this;
- }
-
- public CustomMarkerOptions() {
- }
-
- private CustomMarkerOptions(Parcel in) {
- //Should implement this
- }
-
- @Override
- public CustomMarkerOptions getThis() {
- return this;
+ public static final Parcelable.Creator<CustomMarkerOptions> CREATOR
+ = new Parcelable.Creator<CustomMarkerOptions>() {
+ public CustomMarkerOptions createFromParcel(Parcel in) {
+ return new CustomMarkerOptions(in);
}
- @Override
- public CustomMarker getMarker() {
- return new CustomMarker(this, features);
+ public CustomMarkerOptions[] newArray(int size) {
+ return new CustomMarkerOptions[size];
}
+ };
- public static final Parcelable.Creator<CustomMarkerOptions> CREATOR
- = new Parcelable.Creator<CustomMarkerOptions>() {
- public CustomMarkerOptions createFromParcel(Parcel in) {
- return new CustomMarkerOptions(in);
- }
-
- public CustomMarkerOptions[] newArray(int size) {
- return new CustomMarkerOptions[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
+ @Override
+ public int describeContents() {
+ return 0;
+ }
- @Override
- public void writeToParcel(Parcel out, int flags) {
- //Should implement this
- }
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ //Should implement this
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java
index e97f21327e..1c259b1304 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java
@@ -19,71 +19,71 @@ import com.mapbox.mapboxsdk.testapp.R;
public class MapFragmentActivity extends AppCompatActivity implements OnMapReadyCallback {
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_map_fragment);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_map_fragment);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- MapFragment mapFragment;
- if (savedInstanceState == null) {
- FragmentTransaction transaction = getFragmentManager().beginTransaction();
-
- MapboxMapOptions options = new MapboxMapOptions();
- options.styleUrl(Style.OUTDOORS);
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
- options.scrollGesturesEnabled(false);
- options.zoomGesturesEnabled(false);
- options.tiltGesturesEnabled(false);
- options.rotateGesturesEnabled(false);
+ MapFragment mapFragment;
+ if (savedInstanceState == null) {
+ final FragmentTransaction transaction = getFragmentManager().beginTransaction();
- options.debugActive(false);
+ MapboxMapOptions options = new MapboxMapOptions();
+ options.styleUrl(Style.OUTDOORS);
- LatLng dc = new LatLng(38.90252, -77.02291);
+ options.scrollGesturesEnabled(false);
+ options.zoomGesturesEnabled(false);
+ options.tiltGesturesEnabled(false);
+ options.rotateGesturesEnabled(false);
- options.minZoom(9);
- options.maxZoom(11);
- options.camera(new CameraPosition.Builder()
- .target(dc)
- .zoom(11)
- .build());
+ options.debugActive(false);
- mapFragment = MapFragment.newInstance(options);
+ LatLng dc = new LatLng(38.90252, -77.02291);
- transaction.add(R.id.fragment_container, mapFragment, "com.mapbox.map");
- transaction.commit();
- } else {
- mapFragment = (MapFragment) getFragmentManager().findFragmentByTag("com.mapbox.map");
- }
+ options.minZoomPreference(9);
+ options.maxZoomPreference(11);
+ options.camera(new CameraPosition.Builder()
+ .target(dc)
+ .zoom(11)
+ .build());
- mapFragment.getMapAsync(this);
- }
+ mapFragment = MapFragment.newInstance(options);
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- mapboxMap.animateCamera(
- CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().tilt(45.0).build()), 10000);
+ transaction.add(R.id.fragment_container, mapFragment, "com.mapbox.map");
+ transaction.commit();
+ } else {
+ mapFragment = (MapFragment) getFragmentManager().findFragmentByTag("com.mapbox.map");
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ mapboxMap.animateCamera(
+ CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().tilt(45.0).build()), 10000);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MultiMapActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MultiMapActivity.java
index 526f9ae107..d5d51887dd 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MultiMapActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MultiMapActivity.java
@@ -7,9 +7,9 @@ import com.mapbox.mapboxsdk.testapp.R;
public class MultiMapActivity extends AppCompatActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_multi_map);
- }
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_multi_map);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java
index 03444a871d..7dcca89a04 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java
@@ -19,74 +19,69 @@ import com.mapbox.mapboxsdk.testapp.R;
public class SupportMapFragmentActivity extends AppCompatActivity implements OnMapReadyCallback {
- private MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_map_fragment);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_map_fragment);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- SupportMapFragment mapFragment;
- if (savedInstanceState == null) {
- FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-
- MapboxMapOptions options = new MapboxMapOptions();
- options.styleUrl(Style.SATELLITE_STREETS);
-
- options.scrollGesturesEnabled(false);
- options.zoomGesturesEnabled(false);
- options.tiltGesturesEnabled(false);
- options.rotateGesturesEnabled(false);
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
- options.debugActive(false);
- options.compassEnabled(false);
- options.attributionEnabled(false);
- options.logoEnabled(false);
+ SupportMapFragment mapFragment;
+ if (savedInstanceState == null) {
+ final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- LatLng dc = new LatLng(38.90252, -77.02291);
+ MapboxMapOptions options = new MapboxMapOptions();
+ options.styleUrl(Style.SATELLITE_STREETS);
- options.minZoom(9);
- options.maxZoom(11);
- options.camera(new CameraPosition.Builder()
- .target(dc)
- .zoom(11)
- .build());
+ options.debugActive(false);
+ options.compassEnabled(false);
+ options.attributionEnabled(false);
+ options.logoEnabled(false);
- mapFragment = SupportMapFragment.newInstance(options);
+ LatLng dc = new LatLng(38.90252, -77.02291);
- transaction.add(R.id.fragment_container, mapFragment, "com.mapbox.map");
- transaction.commit();
- } else {
- mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentByTag("com.mapbox.map");
- }
+ options.minZoomPreference(9);
+ options.maxZoomPreference(11);
+ options.camera(new CameraPosition.Builder()
+ .target(dc)
+ .zoom(11)
+ .build());
- mapFragment.getMapAsync(this);
- }
+ mapFragment = SupportMapFragment.newInstance();
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- mapboxMap.animateCamera(
- CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().tilt(45.0).build()), 10000);
+ transaction.add(R.id.fragment_container, mapFragment, "com.mapbox.map");
+ transaction.commit();
+ } else {
+ mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentByTag("com.mapbox.map");
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ mapboxMap.animateCamera(
+ CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().tilt(45.0).build()), 10000);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java
index 6cd3fd62a1..e6953bd3d2 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java
@@ -19,81 +19,81 @@ import com.mapbox.mapboxsdk.testapp.R;
public class ViewPagerActivity extends AppCompatActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_viewpager);
+
+ final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
+ if (viewPager != null) {
+ MapFragmentAdapter adapter = new MapFragmentAdapter(getSupportFragmentManager());
+ viewPager.setAdapter(adapter);
+ }
+ }
+
+ public static class MapFragmentAdapter extends FragmentPagerAdapter {
+
+ private static int NUM_ITEMS = 3;
+
+ public MapFragmentAdapter(FragmentManager fragmentManager) {
+ super(fragmentManager);
+ }
+
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_viewpager);
-
- final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
- if (viewPager != null) {
- MapFragmentAdapter adapter = new MapFragmentAdapter(getSupportFragmentManager());
- viewPager.setAdapter(adapter);
- }
+ public int getCount() {
+ return NUM_ITEMS;
}
- public static class MapFragmentAdapter extends FragmentPagerAdapter {
-
- private static int NUM_ITEMS = 3;
-
- public MapFragmentAdapter(FragmentManager fragmentManager) {
- super(fragmentManager);
- }
-
- @Override
- public int getCount() {
- return NUM_ITEMS;
- }
-
- @Override
- public Fragment getItem(int position) {
- SupportMapFragment fragment = null;
- MapboxMapOptions options = new MapboxMapOptions();
-
- switch (position) {
- case 0:
- options.styleUrl(Style.MAPBOX_STREETS);
- options.camera(new CameraPosition.Builder().target(new LatLng(34.920526, 102.634774)).zoom(3).build());
- fragment = SupportMapFragment.newInstance(options);
- break;
- case 1:
- options.styleUrl(Style.DARK);
- options.camera(new CameraPosition.Builder().target(new LatLng(62.326440, 92.764913)).zoom(3).build());
- fragment = SupportMapFragment.newInstance(options);
- break;
- case 2:
- options.styleUrl(Style.SATELLITE);
- options.camera(new CameraPosition.Builder().target(new LatLng(-25.007786, 133.623852)).zoom(3).build());
- fragment = SupportMapFragment.newInstance(options);
- break;
- }
- return fragment;
- }
-
-
- @Override
- public CharSequence getPageTitle(int position) {
- return "Page " + position;
- }
+ @Override
+ public Fragment getItem(int position) {
+ SupportMapFragment fragment = null;
+ MapboxMapOptions options = new MapboxMapOptions();
+
+ switch (position) {
+ case 0:
+ options.styleUrl(Style.MAPBOX_STREETS);
+ options.camera(new CameraPosition.Builder().target(new LatLng(34.920526, 102.634774)).zoom(3).build());
+ fragment = SupportMapFragment.newInstance(options);
+ break;
+ case 1:
+ options.styleUrl(Style.DARK);
+ options.camera(new CameraPosition.Builder().target(new LatLng(62.326440, 92.764913)).zoom(3).build());
+ fragment = SupportMapFragment.newInstance(options);
+ break;
+ case 2:
+ options.styleUrl(Style.SATELLITE);
+ options.camera(new CameraPosition.Builder().target(new LatLng(-25.007786, 133.623852)).zoom(3).build());
+ fragment = SupportMapFragment.newInstance(options);
+ break;
+ }
+ return fragment;
}
+
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ public CharSequence getPageTitle(int position) {
+ return "Page " + position;
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/geocoding/GeocoderActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/geocoding/GeocoderActivity.java
index baa020fe95..39d52f7876 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/geocoding/GeocoderActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/geocoding/GeocoderActivity.java
@@ -6,7 +6,9 @@ import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.Gravity;
import android.view.MenuItem;
import android.view.ViewGroup;
@@ -22,12 +24,12 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Projection;
import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.services.commons.ServicesException;
+import com.mapbox.services.api.ServicesException;
import com.mapbox.services.commons.models.Position;
-import com.mapbox.services.geocoding.v5.GeocodingCriteria;
-import com.mapbox.services.geocoding.v5.MapboxGeocoding;
-import com.mapbox.services.geocoding.v5.models.CarmenFeature;
-import com.mapbox.services.geocoding.v5.models.GeocodingResponse;
+import com.mapbox.services.api.geocoding.v5.GeocodingCriteria;
+import com.mapbox.services.api.geocoding.v5.MapboxGeocoding;
+import com.mapbox.services.api.geocoding.v5.models.CarmenFeature;
+import com.mapbox.services.api.geocoding.v5.models.GeocodingResponse;
import java.util.List;
@@ -37,157 +39,167 @@ import retrofit2.Response;
public class GeocoderActivity extends AppCompatActivity implements OnMapReadyCallback {
- private static final String LOG_TAG = "GeocoderActivity";
-
- private MapboxMap mapboxMap;
- private MapView mapView;
- private ImageView dropPinView;
- private TextView textView;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_geocoder);
+ private MapboxMap mapboxMap;
+ private MapView mapView;
+ private ImageView dropPinView;
+ private TextView textView;
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_geocoder);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- textView = (TextView) findViewById(R.id.message);
- setMessage(getString(R.string.geocoder_instructions));
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.setStyleUrl(Style.MAPBOX_STREETS);
- mapView.onCreate(savedInstanceState);
-
- dropPinView = new ImageView(this);
- dropPinView.setImageResource(R.drawable.ic_droppin_24dp);
- FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
- dropPinView.setLayoutParams(params);
- mapView.addView(dropPinView);
- mapView.getMapAsync(this);
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- final Projection projection = mapboxMap.getProjection();
- final int width = mapView.getMeasuredWidth();
- final int height = mapView.getMeasuredHeight();
-
- // Click listener
- mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- PointF centerPoint = new PointF(width / 2, (height + dropPinView.getHeight()) / 2);
- LatLng centerLatLng = new LatLng(projection.fromScreenLocation(centerPoint));
+ textView = (TextView) findViewById(R.id.message);
+ setMessage(getString(R.string.geocoder_instructions));
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.setStyleUrl(Style.MAPBOX_STREETS);
+ mapView.onCreate(savedInstanceState);
+
+ dropPinView = new ImageView(this);
+ dropPinView.setImageResource(R.drawable.ic_droppin_24dp);
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
+ dropPinView.setLayoutParams(params);
+ mapView.addView(dropPinView);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ final Projection projection = mapboxMap.getProjection();
+ final int width = mapView.getMeasuredWidth();
+ final int height = mapView.getMeasuredHeight();
+
+ // Click listener
+ mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
+ @Override
+ public void onMapClick(@NonNull LatLng point) {
+ PointF centerPoint = new PointF(width / 2, (height + dropPinView.getHeight()) / 2);
+ LatLng centerLatLng = new LatLng(projection.fromScreenLocation(centerPoint));
+
+ setMessage("Geocoding...");
+
+ mapboxMap.removeAnnotations();
+ mapboxMap.addMarker(new MarkerOptions().position(centerLatLng));
+
+ geocode(centerLatLng);
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ /*
+ * Forward geocoding
+ */
+
+ private void geocode(final LatLng point) {
+
+ try {
+ MapboxGeocoding client = new MapboxGeocoding.Builder()
+ .setAccessToken(getString(R.string.mapbox_access_token))
+ .setCoordinates(Position.fromCoordinates(point.getLongitude(), point.getLatitude()))
+ .setGeocodingType(GeocodingCriteria.TYPE_POI)
+ .build();
+
+ client.enqueueCall(new Callback<GeocodingResponse>() {
+ @Override
+ public void onResponse(Call<GeocodingResponse> call, Response<GeocodingResponse> response) {
+
+ List<CarmenFeature> results = response.body().getFeatures();
+ if (results.size() > 0) {
+ String placeName = results.get(0).getPlaceName();
+ setSuccess(placeName);
+ } else {
+ setMessage("No results.");
+ }
- setMessage("Geocoding...");
-
- mapboxMap.removeAnnotations();
- mapboxMap.addMarker(new MarkerOptions().position(centerLatLng));
-
- geocode(centerLatLng);
- }
- });
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- /*
- * Forward geocoding
- */
-
- private void geocode(final LatLng point) {
-
- try {
- MapboxGeocoding client = new MapboxGeocoding.Builder()
- .setAccessToken(getString(R.string.mapbox_access_token))
- .setCoordinates(Position.fromCoordinates(point.getLongitude(), point.getLatitude()))
- .setGeocodingType(GeocodingCriteria.TYPE_POI)
- .build();
-
- client.enqueueCall(new Callback<GeocodingResponse>() {
- @Override
- public void onResponse(Call<GeocodingResponse> call, Response<GeocodingResponse> response) {
-
- List<CarmenFeature> results = response.body().getFeatures();
- if (results.size() > 0) {
- String placeName = results.get(0).getPlaceName();
- setSuccess(placeName);
- } else {
- setMessage("No results.");
- }
-
- }
-
- @Override
- public void onFailure(Call<GeocodingResponse> call, Throwable throwable) {
- setError(throwable.getMessage());
- }
- });
- } catch (ServicesException servicesException) {
- Log.e(LOG_TAG, "Error geocoding: " + servicesException.toString());
- servicesException.printStackTrace();
- setError(servicesException.getMessage());
}
- }
-
- /*
- * Update text view
- */
- private void setMessage(String message) {
- Log.d(LOG_TAG, "Message: " + message);
- textView.setText(message);
- }
-
- private void setSuccess(String placeName) {
- Log.d(LOG_TAG, "Place name: " + placeName);
- textView.setText(placeName);
- }
-
- private void setError(String message) {
- Log.e(LOG_TAG, "Error: " + message);
- textView.setText("Error: " + message);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ @Override
+ public void onFailure(Call<GeocodingResponse> call, Throwable throwable) {
+ setError(throwable.getMessage());
}
+ });
+ } catch (ServicesException servicesException) {
+ Timber.e("Error geocoding: " + servicesException.toString());
+ servicesException.printStackTrace();
+ setError(servicesException.getMessage());
+ }
+ }
+
+ /*
+ * Update text view
+ */
+
+ private void setMessage(String message) {
+ Timber.d("Message: " + message);
+ textView.setText(message);
+ }
+
+ private void setSuccess(String placeName) {
+ Timber.d("Place name: " + placeName);
+ textView.setText(placeName);
+ }
+
+ private void setError(String message) {
+ Timber.e("Error: " + message);
+ textView.setText("Error: " + message);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/PrintActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/PrintActivity.java
index 18353003d1..7f3c16d7b8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/PrintActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/PrintActivity.java
@@ -17,91 +17,103 @@ import com.mapbox.mapboxsdk.testapp.R;
public class PrintActivity extends AppCompatActivity implements MapboxMap.SnapshotReadyCallback {
- private MapView mapView;
- private MapboxMap mapboxMap;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_print);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_print);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- PrintActivity.this.mapboxMap = mapboxMap;
- }
- });
-
- final View fab = findViewById(R.id.fab);
- if (fab != null) {
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- mapboxMap.snapshot(PrintActivity.this);
- }
- }
- });
- }
- }
-
- @Override
- public void onSnapshotReady(Bitmap snapshot) {
- PrintHelper photoPrinter = new PrintHelper(this);
- photoPrinter.setScaleMode(PrintHelper.SCALE_MODE_FIT);
- photoPrinter.printBitmap("map.jpg - mapbox print job", snapshot);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ PrintActivity.this.mapboxMap = mapboxMap;
+ }
+ });
+
+ final View fab = findViewById(R.id.fab);
+ if (fab != null) {
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (mapboxMap != null) {
+ mapboxMap.snapshot(PrintActivity.this);
+ }
}
+ });
+ }
+ }
+
+ @Override
+ public void onSnapshotReady(Bitmap snapshot) {
+ PrintHelper photoPrinter = new PrintHelper(this);
+ photoPrinter.setScaleMode(PrintHelper.SCALE_MODE_FIT);
+ photoPrinter.printBitmap("map.jpg - mapbox print job", snapshot);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java
index ab4188fd52..3912dfa918 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java
@@ -20,95 +20,107 @@ import com.mapbox.mapboxsdk.testapp.R;
public class SnapshotActivity extends AppCompatActivity implements OnMapReadyCallback, View.OnClickListener {
- private MapView mapView;
- private MapboxMap mapboxMap;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_snapshot);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
- }
-
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- mapboxMap.setStyleUrl(Style.OUTDOORS);
- FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
- if (fab != null) {
- fab.setColorFilter(ContextCompat.getColor(SnapshotActivity.this, R.color.primary));
- fab.setOnClickListener(this);
- }
- }
-
- @Override
- public void onClick(View view) {
- final long startTime = System.nanoTime();
- mapboxMap.snapshot(new MapboxMap.SnapshotReadyCallback() {
- @Override
- public void onSnapshotReady(Bitmap snapshot) {
- long endTime = System.nanoTime();
- long duration = (long) ((endTime - startTime) / 1e6);
- ImageView snapshotView = (ImageView) findViewById(R.id.imageView);
- snapshotView.setImageBitmap(snapshot);
- Toast.makeText(
- SnapshotActivity.this,
- String.format("Snapshot taken in %d ms", duration),
- Toast.LENGTH_LONG).show();
- }
- });
- }
+ private MapView mapView;
+ private MapboxMap mapboxMap;
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_snapshot);
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ mapboxMap.setStyleUrl(Style.OUTDOORS);
+ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ if (fab != null) {
+ fab.setColorFilter(ContextCompat.getColor(SnapshotActivity.this, R.color.primary));
+ fab.setOnClickListener(this);
}
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ }
+
+ @Override
+ public void onClick(View view) {
+ final long startTime = System.nanoTime();
+ mapboxMap.snapshot(new MapboxMap.SnapshotReadyCallback() {
+ @Override
+ public void onSnapshotReady(Bitmap snapshot) {
+ long endTime = System.nanoTime();
+ long duration = (long) ((endTime - startTime) / 1e6);
+ ImageView snapshotView = (ImageView) findViewById(R.id.imageView);
+ snapshotView.setImageBitmap(snapshot);
+ Toast.makeText(
+ SnapshotActivity.this,
+ String.format("Snapshot taken in %d ms", duration),
+ Toast.LENGTH_LONG).show();
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java
index cf522d7f39..c70e263be5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java
@@ -31,142 +31,157 @@ import com.mapbox.mapboxsdk.testapp.R;
*/
public class DynamicInfoWindowAdapterActivity extends AppCompatActivity implements OnMapReadyCallback {
- private MapboxMap mapboxMap;
- private MapView mapView;
+ private MapboxMap mapboxMap;
+ private MapView mapView;
- private LatLng paris = new LatLng(48.864716, 2.349014);
+ private LatLng paris = new LatLng(48.864716, 2.349014);
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_infowindow_adapter);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_infowindow_adapter);
- setupActionBar();
+ setupActionBar();
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
- }
-
- @Override
- public void onMapReady(MapboxMap map) {
-
- mapboxMap = map;
-
- //Add info window adapter
- addCustomInfoWindowAdapter(mapboxMap);
-
- //Keep info windows open on click
- mapboxMap.getUiSettings().setDeselectMarkersOnTap(false);
-
- //Add a marker
- final MarkerView marker = addMarker(mapboxMap);
- mapboxMap.selectMarker(marker);
-
- //On map click, change the info window contents
- mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- //Distance from click to marker
- double distanceKm = marker.getPosition().distanceTo(point) / 1000;
-
- //Get the info window
- InfoWindow infoWindow = marker.getInfoWindow();
-
- //Get the view from the info window
- if (infoWindow != null && infoWindow.getView() != null) {
- //Set the new text on the text view in the info window
- ((TextView) infoWindow.getView()).setText(String.format("%.2fkm", distanceKm));
-
- //Update the info window position (as the text length changes)
- infoWindow.update();
- }
- }
- });
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
- //Focus on Paris
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(paris));
- }
+ @Override
+ public void onMapReady(MapboxMap map) {
- private MarkerView addMarker(MapboxMap mapboxMap) {
- IconFactory iconFactory = IconFactory.getInstance(this);
- Drawable iconDrawable = ContextCompat.getDrawable(this, R.drawable.ic_location_city_24dp);
- iconDrawable.setColorFilter(getResources().getColor(R.color.mapbox_blue), PorterDuff.Mode.SRC_IN);
+ mapboxMap = map;
- return mapboxMap.addMarker(
- new MarkerViewOptions()
- .position(paris)
- .icon(iconFactory.fromDrawable(iconDrawable))
- );
- }
+ //Add info window adapter
+ addCustomInfoWindowAdapter(mapboxMap);
- private void addCustomInfoWindowAdapter(final MapboxMap mapboxMap) {
- final int padding = (int) getResources().getDimension(R.dimen.attr_margin);
- mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
-
- @Nullable
- @Override
- public View getInfoWindow(@NonNull Marker marker) {
- TextView textView = new TextView(DynamicInfoWindowAdapterActivity.this);
- textView.setText(marker.getTitle());
- textView.setBackgroundColor(Color.WHITE);
- textView.setText("Click the map to calculate the distance");
- textView.setPadding(padding, padding, padding, padding);
-
- return textView;
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
+ //Keep info windows open on click
+ mapboxMap.getUiSettings().setDeselectMarkersOnTap(false);
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
+ //Add a marker
+ final MarkerView marker = addMarker(mapboxMap);
+ mapboxMap.selectMarker(marker);
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
+ //On map click, change the info window contents
+ mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
+ @Override
+ public void onMapClick(@NonNull LatLng point) {
+ //Distance from click to marker
+ double distanceKm = marker.getPosition().distanceTo(point) / 1000;
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ //Get the info window
+ InfoWindow infoWindow = marker.getInfoWindow();
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
+ //Get the view from the info window
+ if (infoWindow != null && infoWindow.getView() != null) {
+ //Set the new text on the text view in the info window
+ ((TextView) infoWindow.getView()).setText(String.format("%.2fkm", distanceKm));
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ //Update the info window position (as the text length changes)
+ infoWindow.update();
}
+ }
+ });
+
+ //Focus on Paris
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(paris));
+ }
+
+ private MarkerView addMarker(MapboxMap mapboxMap) {
+ IconFactory iconFactory = IconFactory.getInstance(this);
+ Drawable iconDrawable = ContextCompat.getDrawable(this, R.drawable.ic_location_city_24dp);
+ iconDrawable.setColorFilter(
+ ContextCompat.getColor(DynamicInfoWindowAdapterActivity.this, R.color.mapbox_blue),
+ PorterDuff.Mode.SRC_IN
+ );
+
+ return mapboxMap.addMarker(
+ new MarkerViewOptions()
+ .position(paris)
+ .icon(iconFactory.fromDrawable(iconDrawable))
+ );
+ }
+
+ private void addCustomInfoWindowAdapter(final MapboxMap mapboxMap) {
+ final int padding = (int) getResources().getDimension(R.dimen.attr_margin);
+ mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
+
+ @Nullable
+ @Override
+ public View getInfoWindow(@NonNull Marker marker) {
+ TextView textView = new TextView(DynamicInfoWindowAdapterActivity.this);
+ textView.setText(marker.getTitle());
+ textView.setBackgroundColor(Color.WHITE);
+ textView.setText("Click the map to calculate the distance");
+ textView.setPadding(padding, padding, padding, padding);
+
+ return textView;
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
- private void setupActionBar() {
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ private void setupActionBar() {
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowActivity.java
index 113c46c3e5..0c2af9b7e3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowActivity.java
@@ -8,6 +8,7 @@ import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
+
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
@@ -15,170 +16,183 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.maps.MapView;
+
import java.text.DecimalFormat;
public class InfoWindowActivity extends AppCompatActivity
- implements OnMapReadyCallback, MapboxMap.OnInfoWindowCloseListener, MapboxMap.OnMapLongClickListener,
- MapboxMap.OnInfoWindowClickListener, MapboxMap.OnInfoWindowLongClickListener {
-
- private MapboxMap mapboxMap;
- private MapView mapView;
- private Marker customMarker;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_infowindow);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
- }
-
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- this.mapboxMap = mapboxMap;
- addMarkers();
- addInfoWindowListeners();
- }
-
- private void addMarkers() {
- mapboxMap.addMarker(new MarkerOptions()
- .title("Intersection")
- .snippet("H St NW with 15th St NW")
- .position(new LatLng(38.9002073, -77.03364419)));
-
- mapboxMap.addMarker(new MarkerOptions().title("Intersection")
- .snippet("E St NW with 17th St NW")
- .position(new LatLng(38.8954236, -77.0394623)));
-
- mapboxMap.addMarker(new MarkerOptions().title("The Ellipse").position(new LatLng(38.89393, -77.03654)));
-
- mapboxMap.addMarker(new MarkerOptions().position(new LatLng(38.89596, -77.03434)));
-
- mapboxMap.addMarker(new MarkerOptions().snippet("Lafayette Square").position(new LatLng(38.89949, -77.03656)));
-
- Marker marker = mapboxMap.addMarker(new MarkerOptions()
- .title("White House")
- .snippet("The official residence and principal workplace of the President of the United States, "
- + "located at 1600 Pennsylvania Avenue NW in Washington, D.C. It has been the residence of every"
- + "U.S. president since John Adams in 1800.")
- .position(new LatLng(38.897705003219784, -77.03655168667463)));
-
- // open InfoWindow at startup
- mapboxMap.selectMarker(marker);
- }
-
- private void addInfoWindowListeners() {
- mapboxMap.setOnInfoWindowCloseListener(this);
- mapboxMap.setOnMapLongClickListener(this);
- mapboxMap.setOnInfoWindowClickListener(this);
- mapboxMap.setOnInfoWindowLongClickListener(this);
- }
-
- private void toggleConcurrentInfoWindow(boolean allowConcurrentInfoWindow) {
- mapboxMap.deselectMarkers();
- mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(allowConcurrentInfoWindow);
- }
-
- private void toggleDeselectMarkersOnTap(boolean deselectMarkersOnTap) {
- mapboxMap.getUiSettings().setDeselectMarkersOnTap(deselectMarkersOnTap);
- }
-
- @Override
- public boolean onInfoWindowClick(@NonNull Marker marker) {
- Toast.makeText(getApplicationContext(), "OnClick: " + marker.getTitle(), Toast.LENGTH_LONG).show();
- // returning true will leave the info window open
- return false;
- }
-
- @Override
- public void onInfoWindowClose(Marker marker) {
- Toast.makeText(getApplicationContext(), "OnClose: " + marker.getTitle(), Toast.LENGTH_LONG).show();
- }
-
- @Override
- public void onInfoWindowLongClick(Marker marker) {
- Toast.makeText(getApplicationContext(), "OnLongClick: " + marker.getTitle(), Toast.LENGTH_LONG).show();
- }
-
- @Override
- public void onMapLongClick(@NonNull LatLng point) {
- if (customMarker != null) {
- // Remove previous added marker
- mapboxMap.removeAnnotation(customMarker);
- customMarker = null;
- }
-
- // Add marker on long click location with default marker image
- customMarker = mapboxMap.addMarker(new MarkerOptions()
- .title("Custom Marker")
- .snippet(new DecimalFormat("#.#####").format(point.getLatitude()) + ", "
- + new DecimalFormat("#.#####").format(point.getLongitude()))
- .position(point));
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_infowindow, menu);
+ implements OnMapReadyCallback, MapboxMap.OnInfoWindowCloseListener, MapboxMap.OnMapLongClickListener,
+ MapboxMap.OnInfoWindowClickListener, MapboxMap.OnInfoWindowLongClickListener {
+
+ private MapboxMap mapboxMap;
+ private MapView mapView;
+ private Marker customMarker;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_infowindow);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ addMarkers();
+ addInfoWindowListeners();
+ }
+
+ private void addMarkers() {
+ mapboxMap.addMarker(new MarkerOptions()
+ .title("Intersection")
+ .snippet("H St NW with 15th St NW")
+ .position(new LatLng(38.9002073, -77.03364419)));
+
+ mapboxMap.addMarker(new MarkerOptions().title("Intersection")
+ .snippet("E St NW with 17th St NW")
+ .position(new LatLng(38.8954236, -77.0394623)));
+
+ mapboxMap.addMarker(new MarkerOptions().title("The Ellipse").position(new LatLng(38.89393, -77.03654)));
+
+ mapboxMap.addMarker(new MarkerOptions().position(new LatLng(38.89596, -77.03434)));
+
+ mapboxMap.addMarker(new MarkerOptions().snippet("Lafayette Square").position(new LatLng(38.89949, -77.03656)));
+
+ Marker marker = mapboxMap.addMarker(new MarkerOptions()
+ .title("White House")
+ .snippet("The official residence and principal workplace of the President of the United States, "
+ + "located at 1600 Pennsylvania Avenue NW in Washington, D.C. It has been the residence of every"
+ + "U.S. president since John Adams in 1800.")
+ .position(new LatLng(38.897705003219784, -77.03655168667463)));
+
+ // open InfoWindow at startup
+ mapboxMap.selectMarker(marker);
+ }
+
+ private void addInfoWindowListeners() {
+ mapboxMap.setOnInfoWindowCloseListener(this);
+ mapboxMap.setOnMapLongClickListener(this);
+ mapboxMap.setOnInfoWindowClickListener(this);
+ mapboxMap.setOnInfoWindowLongClickListener(this);
+ }
+
+ private void toggleConcurrentInfoWindow(boolean allowConcurrentInfoWindow) {
+ mapboxMap.deselectMarkers();
+ mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(allowConcurrentInfoWindow);
+ }
+
+ private void toggleDeselectMarkersOnTap(boolean deselectMarkersOnTap) {
+ mapboxMap.getUiSettings().setDeselectMarkersOnTap(deselectMarkersOnTap);
+ }
+
+ @Override
+ public boolean onInfoWindowClick(@NonNull Marker marker) {
+ Toast.makeText(getApplicationContext(), "OnClick: " + marker.getTitle(), Toast.LENGTH_LONG).show();
+ // returning true will leave the info window open
+ return false;
+ }
+
+ @Override
+ public void onInfoWindowClose(Marker marker) {
+ Toast.makeText(getApplicationContext(), "OnClose: " + marker.getTitle(), Toast.LENGTH_LONG).show();
+ }
+
+ @Override
+ public void onInfoWindowLongClick(Marker marker) {
+ Toast.makeText(getApplicationContext(), "OnLongClick: " + marker.getTitle(), Toast.LENGTH_LONG).show();
+ }
+
+ @Override
+ public void onMapLongClick(@NonNull LatLng point) {
+ if (customMarker != null) {
+ // Remove previous added marker
+ mapboxMap.removeAnnotation(customMarker);
+ customMarker = null;
+ }
+
+ // Add marker on long click location with default marker image
+ customMarker = mapboxMap.addMarker(new MarkerOptions()
+ .title("Custom Marker")
+ .snippet(new DecimalFormat("#.#####").format(point.getLatitude()) + ", "
+ + new DecimalFormat("#.#####").format(point.getLongitude()))
+ .position(point));
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_infowindow, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_toggle_concurrent_infowindow:
+ toggleConcurrentInfoWindow(!item.isChecked());
+ item.setChecked(!item.isChecked());
return true;
+ case R.id.action_toggle_deselect_markers_on_tap:
+ toggleDeselectMarkersOnTap(!item.isChecked());
+ item.setChecked(!item.isChecked());
+ return true;
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_toggle_concurrent_infowindow:
- toggleConcurrentInfoWindow(!item.isChecked());
- item.setChecked(!item.isChecked());
- return true;
- case R.id.action_toggle_deselect_markers_on_tap:
- toggleDeselectMarkersOnTap(!item.isChecked());
- item.setChecked(!item.isChecked());
- return true;
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java
index 8066dbc60e..08f64abcba 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java
@@ -26,121 +26,133 @@ import com.mapbox.mapboxsdk.testapp.model.annotations.CityStateMarkerOptions;
public class InfoWindowAdapterActivity extends AppCompatActivity {
- private MapView mapView;
- private MapboxMap mapboxMap;
- private IconFactory iconFactory;
- private Drawable iconDrawable;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_infowindow_adapter);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- iconFactory = IconFactory.getInstance(this);
- iconDrawable = ContextCompat.getDrawable(this, R.drawable.ic_location_city_24dp);
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap map) {
- mapboxMap = map;
- addMarkers();
- addCustomInfoWindowAdapter();
- }
- });
- }
-
- private void addMarkers() {
- mapboxMap.addMarker(generateCityStateMarker("Andorra", 42.505777, 1.52529, "#F44336"));
- mapboxMap.addMarker(generateCityStateMarker("Luxembourg", 49.815273, 6.129583, "#3F51B5"));
- mapboxMap.addMarker(generateCityStateMarker("Monaco", 43.738418, 7.424616, "#673AB7"));
- mapboxMap.addMarker(generateCityStateMarker("Vatican City", 41.902916, 12.453389, "#009688"));
- mapboxMap.addMarker(generateCityStateMarker("San Marino", 43.942360, 12.457777, "#795548"));
- mapboxMap.addMarker(generateCityStateMarker("Liechtenstein", 47.166000, 9.555373, "#FF5722"));
- }
-
- private CityStateMarkerOptions generateCityStateMarker(String title, double lat, double lng, String color) {
- CityStateMarkerOptions marker = new CityStateMarkerOptions();
- marker.title(title);
- marker.position(new LatLng(lat, lng));
- marker.infoWindowBackground(color);
-
- iconDrawable.setColorFilter(Color.parseColor(color), PorterDuff.Mode.SRC_IN);
- Icon icon = iconFactory.fromDrawable(iconDrawable);
- marker.icon(icon);
- return marker;
- }
-
- private void addCustomInfoWindowAdapter() {
- mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
-
- private int tenDp = (int) getResources().getDimension(R.dimen.attr_margin);
-
- @Override
- public View getInfoWindow(@NonNull Marker marker) {
- TextView textView = new TextView(InfoWindowAdapterActivity.this);
- textView.setText(marker.getTitle());
- textView.setTextColor(Color.WHITE);
-
- if (marker instanceof CityStateMarker) {
- CityStateMarker cityStateMarker = (CityStateMarker) marker;
- textView.setBackgroundColor(Color.parseColor(cityStateMarker.getInfoWindowBackgroundColor()));
- }
-
- textView.setPadding(tenDp, tenDp, tenDp, tenDp);
- return textView;
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private IconFactory iconFactory;
+ private Drawable iconDrawable;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_infowindow_adapter);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ iconFactory = IconFactory.getInstance(this);
+ iconDrawable = ContextCompat.getDrawable(this, R.drawable.ic_location_city_24dp);
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap map) {
+ mapboxMap = map;
+ addMarkers();
+ addCustomInfoWindowAdapter();
+ }
+ });
+ }
+
+ private void addMarkers() {
+ mapboxMap.addMarker(generateCityStateMarker("Andorra", 42.505777, 1.52529, "#F44336"));
+ mapboxMap.addMarker(generateCityStateMarker("Luxembourg", 49.815273, 6.129583, "#3F51B5"));
+ mapboxMap.addMarker(generateCityStateMarker("Monaco", 43.738418, 7.424616, "#673AB7"));
+ mapboxMap.addMarker(generateCityStateMarker("Vatican City", 41.902916, 12.453389, "#009688"));
+ mapboxMap.addMarker(generateCityStateMarker("San Marino", 43.942360, 12.457777, "#795548"));
+ mapboxMap.addMarker(generateCityStateMarker("Liechtenstein", 47.166000, 9.555373, "#FF5722"));
+ }
+
+ private CityStateMarkerOptions generateCityStateMarker(String title, double lat, double lng, String color) {
+ CityStateMarkerOptions marker = new CityStateMarkerOptions();
+ marker.title(title);
+ marker.position(new LatLng(lat, lng));
+ marker.infoWindowBackground(color);
+
+ iconDrawable.setColorFilter(Color.parseColor(color), PorterDuff.Mode.SRC_IN);
+ Icon icon = iconFactory.fromDrawable(iconDrawable);
+ marker.icon(icon);
+ return marker;
+ }
+
+ private void addCustomInfoWindowAdapter() {
+ mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
+
+ private int tenDp = (int) getResources().getDimension(R.dimen.attr_margin);
+
+ @Override
+ public View getInfoWindow(@NonNull Marker marker) {
+ TextView textView = new TextView(InfoWindowAdapterActivity.this);
+ textView.setText(marker.getTitle());
+ textView.setTextColor(Color.WHITE);
+
+ if (marker instanceof CityStateMarker) {
+ CityStateMarker cityStateMarker = (CityStateMarker) marker;
+ textView.setBackgroundColor(Color.parseColor(cityStateMarker.getInfoWindowBackgroundColor()));
}
+
+ textView.setPadding(tenDp, tenDp, tenDp, tenDp);
+ return textView;
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java
index 377d5d18f0..5c9d927e9b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java
@@ -6,7 +6,9 @@ import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.MenuItem;
import android.view.View;
@@ -18,113 +20,123 @@ import com.mapbox.mapboxsdk.testapp.R;
public class DebugModeActivity extends AppCompatActivity {
- private static final String TAG = "DebugModeActivity";
-
- private MapView mapView;
- private MapboxMap mapboxMap;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
- private int currentStyleIndex = 0;
+ private int currentStyleIndex = 0;
- private static final String[] STYLES = new String[]{
- Style.MAPBOX_STREETS,
- Style.OUTDOORS,
- Style.LIGHT,
- Style.DARK,
- Style.SATELLITE,
- Style.SATELLITE_STREETS
- };
+ private static final String[] STYLES = new String[] {
+ Style.MAPBOX_STREETS,
+ Style.OUTDOORS,
+ Style.LIGHT,
+ Style.DARK,
+ Style.SATELLITE,
+ Style.SATELLITE_STREETS
+ };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_debug_mode);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_debug_mode);
- final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.setTag(true);
- mapView.setStyleUrl(STYLES[currentStyleIndex]);
- mapView.onCreate(savedInstanceState);
-
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap map) {
- mapboxMap = map;
- }
- });
-
- FloatingActionButton fabDebug = (FloatingActionButton) findViewById(R.id.fabDebug);
- fabDebug.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- Log.d(TAG, "Debug FAB: isDebug Active? " + mapboxMap.isDebugActive());
- mapboxMap.cycleDebugOptions();
- }
- }
- });
-
- FloatingActionButton fabStyles = (FloatingActionButton) findViewById(R.id.fabStyles);
- fabStyles.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- currentStyleIndex++;
- if (currentStyleIndex == STYLES.length) {
- currentStyleIndex = 0;
- }
- mapboxMap.setStyleUrl(STYLES[currentStyleIndex]);
- }
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
+ final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
-
- default:
- return super.onOptionsItemSelected(item);
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.setTag(true);
+ mapView.setStyleUrl(STYLES[currentStyleIndex]);
+ mapView.onCreate(savedInstanceState);
+
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap map) {
+ mapboxMap = map;
+ }
+ });
+
+ FloatingActionButton fabDebug = (FloatingActionButton) findViewById(R.id.fabDebug);
+ fabDebug.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (mapboxMap != null) {
+ Timber.d("Debug FAB: isDebug Active? " + mapboxMap.isDebugActive());
+ mapboxMap.cycleDebugOptions();
+ }
+ }
+ });
+
+ FloatingActionButton fabStyles = (FloatingActionButton) findViewById(R.id.fabStyles);
+ fabStyles.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (mapboxMap != null) {
+ currentStyleIndex++;
+ if (currentStyleIndex == STYLES.length) {
+ currentStyleIndex = 0;
+ }
+ mapboxMap.setStyleUrl(STYLES[currentStyleIndex]);
}
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java
index b34962a792..6c43e28237 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java
@@ -28,165 +28,176 @@ import com.mapbox.mapboxsdk.testapp.R;
public class DoubleMapActivity extends AppCompatActivity {
- private static final String TAG_FRAGMENT = "map";
+ private static final String TAG_FRAGMENT = "map";
- // used for ui tests
- private MapboxMap mapboxMap;
+ // used for ui tests
+ private MapboxMap mapboxMap;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_map_fragment);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_map_fragment);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
- Fragment mapFragment;
- if (savedInstanceState == null) {
- FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- transaction.add(R.id.fragment_container, mapFragment = new DoubleMapFragment(), TAG_FRAGMENT);
- transaction.commit();
- } else {
- mapFragment = (DoubleMapFragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);
- }
+ if (savedInstanceState == null) {
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.add(R.id.fragment_container, new DoubleMapFragment(), TAG_FRAGMENT);
+ transaction.commit();
+ }
+ }
+
+ public void setMapboxMap(MapboxMap map) {
+ // we need to set mapboxmap on the parent activity,
+ // for auto-generated ui tests
+
+ mapboxMap = map;
+ mapboxMap.setStyleUrl(Style.DARK);
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(18));
+ try {
+ TrackingSettings settings = mapboxMap.getTrackingSettings();
+ settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
+ } catch (SecurityException securityException) {
+ // permission is handled in MainActivity
+ finish();
}
+ }
- public void setMapboxMap(MapboxMap map) {
- // we need to set mapboxmap on the parent activity,
- // for auto-generated ui tests
+ public static class DoubleMapFragment extends Fragment {
- mapboxMap = map;
- mapboxMap.setStyleUrl(Style.DARK);
- mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(18));
- try {
- TrackingSettings settings = mapboxMap.getTrackingSettings();
- settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- } catch (SecurityException securityException) {
- // permission is handled in MainActivity
- finish();
- }
+ private DoubleMapActivity activity;
+ private MapView mapView;
+ private MapView mapViewMini;
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ activity = (DoubleMapActivity) context;
}
- public static class DoubleMapFragment extends Fragment {
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_double_map, container, false);
+ }
- private DoubleMapActivity activity;
- private MapView mapView;
- private MapView mapViewMini;
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ // MapView large
+ mapView = (MapView) view.findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
@Override
- public void onAttach(Context context) {
- super.onAttach(context);
- activity = (DoubleMapActivity) context;
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ if (activity != null) {
+ activity.setMapboxMap(mapboxMap);
+ }
}
+ });
+ // MapView mini
+ mapViewMini = (MapView) view.findViewById(R.id.mini_map);
+ mapViewMini.onCreate(savedInstanceState);
+ mapViewMini.getMapAsync(new OnMapReadyCallback() {
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- return inflater.inflate(R.layout.fragment_double_map, container, false);
- }
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ mapboxMap.setStyleUrl(Style.LIGHT);
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4));
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- // MapView large
- mapView = (MapView) view.findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- if (activity != null) {
- activity.setMapboxMap(mapboxMap);
- }
- }
- });
-
- // MapView mini
- mapViewMini = (MapView) view.findViewById(R.id.mini_map);
- mapViewMini.onCreate(savedInstanceState);
- mapViewMini.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- mapboxMap.setStyleUrl(Style.LIGHT);
- mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4));
-
- UiSettings uiSettings = mapboxMap.getUiSettings();
- uiSettings.setAllGesturesEnabled(false);
- uiSettings.setCompassEnabled(false);
- uiSettings.setAttributionEnabled(false);
- uiSettings.setLogoEnabled(false);
-
- try {
- TrackingSettings settings = mapboxMap.getTrackingSettings();
- settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- } catch (SecurityException securityException) {
- // permission is handled in MainActivity
- getActivity().finish();
- }
-
- mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- // test if we can open 2 activities after each other
- startActivity(new Intent(mapViewMini.getContext(), DoubleMapActivity.class));
- }
- });
- }
- });
-
- SurfaceView surfaceViewMini = (SurfaceView) mapViewMini.findViewById(R.id.surfaceView);
- surfaceViewMini.setZOrderMediaOverlay(true);
- }
+ UiSettings uiSettings = mapboxMap.getUiSettings();
+ uiSettings.setAllGesturesEnabled(false);
+ uiSettings.setCompassEnabled(false);
+ uiSettings.setAttributionEnabled(false);
+ uiSettings.setLogoEnabled(false);
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- mapViewMini.onResume();
+ try {
+ TrackingSettings settings = mapboxMap.getTrackingSettings();
+ settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
+ } catch (SecurityException securityException) {
+ // permission is handled in MainActivity
+ getActivity().finish();
+ }
+
+ mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
+ @Override
+ public void onMapClick(@NonNull LatLng point) {
+ // test if we can open 2 activities after each other
+ startActivity(new Intent(mapViewMini.getContext(), DoubleMapActivity.class));
+ }
+ });
}
+ });
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- mapViewMini.onPause();
- }
+ SurfaceView surfaceViewMini = (SurfaceView) mapViewMini.findViewById(R.id.surfaceView);
+ surfaceViewMini.setZOrderMediaOverlay(true);
+ }
- @Override
- public void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- mapViewMini.onDestroy();
- }
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ mapViewMini.onResume();
+ }
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- mapViewMini.onLowMemory();
- }
+ @Override
+ public void onStart() {
+ super.onStart();
+ mapView.onStart();
+ mapViewMini.onStart();
+ }
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- mapViewMini.onSaveInstanceState(outState);
- }
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ mapViewMini.onPause();
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ public void onStop() {
+ super.onStop();
+ mapView.onStop();
+ mapViewMini.onStop();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ mapViewMini.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ mapViewMini.onLowMemory();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ mapViewMini.onSaveInstanceState(outState);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java
index 3df236f43c..ed3f315e06 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java
@@ -14,103 +14,114 @@ import android.view.ViewGroup;
import android.widget.Button;
import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
public class MapInDialogActivity extends AppCompatActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_map_in_dialog);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ Button button = (Button) findViewById(R.id.button_open_dialog);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ FragmentManager fm = getSupportFragmentManager();
+ MapDialogFragment editNameDialogFragment = MapDialogFragment.newInstance("Map Dialog");
+ editNameDialogFragment.show(fm, "fragment_dialog_map");
+ }
+ });
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ public static class MapDialogFragment extends DialogFragment {
+
+ private MapView mapView;
+
+ public MapDialogFragment() {
+ }
+
+ public static MapDialogFragment newInstance(String title) {
+ MapDialogFragment frag = new MapDialogFragment();
+ Bundle args = new Bundle();
+ args.putString("title", title);
+ frag.setArguments(args);
+ return frag;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_dialog_map, container);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ mapView = (MapView) view.findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_map_in_dialog);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- Button button = (Button) findViewById(R.id.button_open_dialog);
- button.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- FragmentManager fm = getSupportFragmentManager();
- MapDialogFragment editNameDialogFragment = MapDialogFragment.newInstance("Map Dialog");
- editNameDialogFragment.show(fm, "fragment_dialog_map");
- }
- });
+ public void onStop() {
+ super.onStop();
+ mapView.onStop();
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ public void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
}
- public static class MapDialogFragment extends DialogFragment {
-
- private MapView mapView;
-
- public MapDialogFragment() {}
-
- public static MapDialogFragment newInstance(String title) {
- MapDialogFragment frag = new MapDialogFragment();
- Bundle args = new Bundle();
- args.putString("title", title);
- frag.setArguments(args);
- return frag;
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- return inflater.inflate(R.layout.fragment_dialog_map, container);
- }
-
- @Override
- public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- mapView = (MapView) view.findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
}
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java
index 114262220a..90b91057ed 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java
@@ -21,131 +21,143 @@ import com.mapbox.mapboxsdk.testapp.R;
public class MapPaddingActivity extends AppCompatActivity {
- private MapView mapView;
- private MapboxMap mapboxMap;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_map_padding);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_map_padding);
- final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.setTag(true);
- mapView.onCreate(savedInstanceState);
-
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- MapPaddingActivity.this.mapboxMap = mapboxMap;
-
- int paddingLeft = (int) getResources().getDimension(R.dimen.map_padding_left);
- int paddingBottom = (int) getResources().getDimension(R.dimen.map_padding_bottom);
- int paddingRight = (int) getResources().getDimension(R.dimen.map_padding_right);
- mapboxMap.setPadding(paddingLeft, toolbar.getHeight(), paddingRight, paddingBottom);
-
- moveToBangalore();
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.setTag(true);
+ mapView.onCreate(savedInstanceState);
+
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ MapPaddingActivity.this.mapboxMap = mapboxMap;
+
+ int paddingLeft = (int) getResources().getDimension(R.dimen.map_padding_left);
+ int paddingBottom = (int) getResources().getDimension(R.dimen.map_padding_bottom);
+ int paddingRight = (int) getResources().getDimension(R.dimen.map_padding_right);
+ mapboxMap.setPadding(paddingLeft, toolbar.getHeight(), paddingRight, paddingBottom);
+
+ moveToBangalore();
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_padding, menu);
+ return true;
+ }
+
+ private void toggleGps(boolean enable) {
+ try {
+ // Enable user location
+ mapboxMap.setMyLocationEnabled(enable);
+
+ TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
+ trackingSettings.setDismissLocationTrackingOnGesture(false);
+ trackingSettings.setMyLocationTrackingMode(
+ enable ? MyLocationTracking.TRACKING_FOLLOW : MyLocationTracking.TRACKING_NONE);
+ } catch (SecurityException securityException) {
+ // permission not granted is handled in FeatureOverviewActivity
+ finish();
}
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_padding, menu);
+ }
+
+ private void moveToBangalore() {
+ toggleGps(false);
+
+ LatLng bangalore = new LatLng(12.9810816, 77.6368034);
+ CameraPosition cameraPosition = new CameraPosition.Builder()
+ .zoom(16)
+ .target(bangalore)
+ .bearing(40)
+ .tilt(45)
+ .build();
+
+ mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
+ mapboxMap.addMarker(new MarkerOptions().title("Center map").position(bangalore));
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
return true;
- }
- private void toggleGps(boolean enable) {
- try {
- // Enable user location
- mapboxMap.setMyLocationEnabled(enable);
-
- TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
- trackingSettings.setDismissTrackingOnGesture(false);
- trackingSettings.setMyLocationTrackingMode(
- enable ? MyLocationTracking.TRACKING_FOLLOW : MyLocationTracking.TRACKING_NONE);
- } catch (SecurityException securityException) {
- // permission not granted is handled in FeatureOverviewActivity
- finish();
+ case R.id.action_user_tracking:
+ if (mapboxMap != null) {
+ toggleGps(true);
}
- }
-
- private void moveToBangalore() {
- toggleGps(false);
-
- LatLng bangalore = new LatLng(12.9810816, 77.6368034);
- CameraPosition cameraPosition = new CameraPosition.Builder()
- .zoom(16)
- .target(bangalore)
- .bearing(40)
- .tilt(45)
- .build();
-
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
- mapboxMap.addMarker(new MarkerOptions().title("Center map").position(bangalore));
- }
+ return true;
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
-
- case R.id.action_user_tracking:
- if (mapboxMap != null) {
- toggleGps(true);
- }
- return true;
-
- case R.id.action_bangalore:
- if (mapboxMap != null) {
- moveToBangalore();
- }
- return true;
-
- default:
- return super.onOptionsItemSelected(item);
+ case R.id.action_bangalore:
+ if (mapboxMap != null) {
+ moveToBangalore();
}
+ return true;
+
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/NavigationDrawerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/NavigationDrawerActivity.java
index 76363ef808..7f59dd3bdb 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/NavigationDrawerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/NavigationDrawerActivity.java
@@ -32,221 +32,221 @@ import com.mapbox.mapboxsdk.testapp.R;
public class NavigationDrawerActivity extends AppCompatActivity {
- private boolean firstStyle = true;
- private MapboxMap mapboxMap;
+ private boolean firstStyle = true;
+ private MapboxMap mapboxMap;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_navigation_drawer);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ NavigationDrawerFragment navigationDrawerFragment;
+
+ getFragmentManager()
+ .beginTransaction()
+ .add(R.id.navigation_drawer, navigationDrawerFragment = new NavigationDrawerFragment())
+ .commit();
+
+ navigationDrawerFragment.setUp(this,
+ R.id.navigation_drawer,
+ (DrawerLayout) findViewById(R.id.drawer_layout),
+ getSupportActionBar());
+ }
+
+ public void onNavigationDrawerItemSelected(int position) {
+ // update the main content by replacing fragments
+ switch (position) {
+ case 0:
+ // options
+ MapboxMapOptions options = new MapboxMapOptions();
+ options.styleUrl(firstStyle ? Style.LIGHT : Style.SATELLITE);
+ options.camera(new CameraPosition.Builder()
+ .target(new LatLng(39.913271, 116.413891))
+ .zoom(12)
+ .build());
+
+ // fragment
+ MapFragment mapFragment = MapFragment.newInstance(options);
+ FragmentManager fragmentManager = getFragmentManager();
+ fragmentManager.beginTransaction()
+ .replace(R.id.container, mapFragment)
+ .commit();
+
+ // get callback when map is ready
+ mapFragment.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ }
+ });
+
+ firstStyle = !firstStyle;
+ break;
+ case 1:
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ "Hello from snackbar",
+ Snackbar.LENGTH_LONG)
+ .show();
+ break;
+ }
+ }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_navigation_drawer);
+ public static class NavigationDrawerFragment extends Fragment {
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";
+ private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
- NavigationDrawerFragment navigationDrawerFragment;
+ private ActionBarDrawerToggle drawerToggle;
- getFragmentManager()
- .beginTransaction()
- .add(R.id.navigation_drawer, navigationDrawerFragment = new NavigationDrawerFragment())
- .commit();
+ private DrawerLayout drawerLayout;
+ private ListView drawerListView;
+ private View fragmentContainerView;
- navigationDrawerFragment.setUp(this,
- R.id.navigation_drawer,
- (DrawerLayout) findViewById(R.id.drawer_layout),
- getSupportActionBar());
- }
+ private int currentSelectedPosition = 0;
+ private boolean fromSavedInstanceState;
+ private boolean userLearnedDrawer;
- public void onNavigationDrawerItemSelected(int position) {
- // update the main content by replacing fragments
- switch (position) {
- case 0:
- // options
- MapboxMapOptions options = new MapboxMapOptions();
- options.styleUrl(firstStyle ? Style.LIGHT : Style.SATELLITE);
- options.camera(new CameraPosition.Builder()
- .target(new LatLng(39.913271, 116.413891))
- .zoom(12)
- .build());
-
- // fragment
- MapFragment mapFragment = MapFragment.newInstance(options);
- FragmentManager fragmentManager = getFragmentManager();
- fragmentManager.beginTransaction()
- .replace(R.id.container, mapFragment)
- .commit();
-
- // get callback when map is ready
- mapFragment.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- }
- });
-
- firstStyle = !firstStyle;
- break;
- case 1:
- Snackbar.make(
- findViewById(android.R.id.content),
- "Hello from snackbar",
- Snackbar.LENGTH_LONG)
- .show();
- break;
- }
+ public NavigationDrawerFragment() {
}
- public static class NavigationDrawerFragment extends Fragment {
-
- private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";
- private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
-
- private ActionBarDrawerToggle drawerToggle;
-
- private DrawerLayout drawerLayout;
- private ListView drawerListView;
- private View fragmentContainerView;
-
- private int currentSelectedPosition = 0;
- private boolean fromSavedInstanceState;
- private boolean userLearnedDrawer;
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ userLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);
+
+ if (savedInstanceState != null) {
+ currentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
+ fromSavedInstanceState = true;
+ }
+ selectItem(currentSelectedPosition);
+ }
- public NavigationDrawerFragment() {
- }
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ drawerListView = (ListView) inflater.inflate(
+ R.layout.drawer_navigation_drawer, container, false);
+ drawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
- userLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);
-
- if (savedInstanceState != null) {
- currentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
- fromSavedInstanceState = true;
- }
- selectItem(currentSelectedPosition);
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ selectItem(position);
}
+ });
+ drawerListView.setAdapter(new ArrayAdapter<>(
+ inflater.getContext(),
+ android.R.layout.simple_list_item_activated_1,
+ android.R.id.text1,
+ new String[] {
+ getString(R.string.title_section1),
+ getString(R.string.title_section2)
+ }));
+ drawerListView.setItemChecked(currentSelectedPosition, true);
+ return drawerListView;
+ }
+ /**
+ * Users of this fragment must call this method to set up the navigation drawer interactions.
+ *
+ * @param fragmentId The android:id of this fragment in its activity's layout.
+ * @param drawerLayout The DrawerLayout containing this fragment's UI.
+ */
+ public void setUp(Activity activity, int fragmentId, DrawerLayout drawerLayout, ActionBar actionBar) {
+ fragmentContainerView = activity.findViewById(fragmentId);
+ this.drawerLayout = drawerLayout;
+ // drawerLayout.setScrimColor(Color.TRANSPARENT);
+
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setHomeButtonEnabled(true);
+
+ drawerToggle = new ActionBarDrawerToggle(
+ activity,
+ NavigationDrawerFragment.this.drawerLayout,
+ R.string.navigation_drawer_open,
+ R.string.navigation_drawer_close
+ ) {
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- setHasOptionsMenu(true);
+ public void onDrawerClosed(View drawerView) {
+ super.onDrawerClosed(drawerView);
+ if (!isAdded()) {
+ return;
+ }
+ getActivity().invalidateOptionsMenu();
}
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- drawerListView = (ListView) inflater.inflate(
- R.layout.drawer_navigation_drawer, container, false);
- drawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- selectItem(position);
- }
- });
- drawerListView.setAdapter(new ArrayAdapter<>(
- inflater.getContext(),
- android.R.layout.simple_list_item_activated_1,
- android.R.id.text1,
- new String[]{
- getString(R.string.title_section1),
- getString(R.string.title_section2)
- }));
- drawerListView.setItemChecked(currentSelectedPosition, true);
- return drawerListView;
+ public void onDrawerOpened(View drawerView) {
+ super.onDrawerOpened(drawerView);
+ if (!isAdded()) {
+ return;
+ }
+
+ if (!userLearnedDrawer) {
+ userLearnedDrawer = true;
+ SharedPreferences sp = PreferenceManager
+ .getDefaultSharedPreferences(getActivity());
+ sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
+ }
+ getActivity().invalidateOptionsMenu();
}
+ };
- /**
- * Users of this fragment must call this method to set up the navigation drawer interactions.
- *
- * @param fragmentId The android:id of this fragment in its activity's layout.
- * @param drawerLayout The DrawerLayout containing this fragment's UI.
- */
- public void setUp(Activity activity, int fragmentId, DrawerLayout drawerLayout, ActionBar actionBar) {
- fragmentContainerView = activity.findViewById(fragmentId);
- this.drawerLayout = drawerLayout;
- // drawerLayout.setScrimColor(Color.TRANSPARENT);
-
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setHomeButtonEnabled(true);
-
- drawerToggle = new ActionBarDrawerToggle(
- activity,
- NavigationDrawerFragment.this.drawerLayout,
- R.string.navigation_drawer_open,
- R.string.navigation_drawer_close
- ) {
- @Override
- public void onDrawerClosed(View drawerView) {
- super.onDrawerClosed(drawerView);
- if (!isAdded()) {
- return;
- }
- getActivity().invalidateOptionsMenu();
- }
-
- @Override
- public void onDrawerOpened(View drawerView) {
- super.onDrawerOpened(drawerView);
- if (!isAdded()) {
- return;
- }
-
- if (!userLearnedDrawer) {
- userLearnedDrawer = true;
- SharedPreferences sp = PreferenceManager
- .getDefaultSharedPreferences(getActivity());
- sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
- }
- getActivity().invalidateOptionsMenu();
- }
- };
-
- if (!userLearnedDrawer && !fromSavedInstanceState) {
- this.drawerLayout.openDrawer(fragmentContainerView);
- }
- this.drawerLayout.post(new Runnable() {
- @Override
- public void run() {
- drawerToggle.syncState();
- }
- });
- this.drawerLayout.setDrawerListener(drawerToggle);
+ if (!userLearnedDrawer && !fromSavedInstanceState) {
+ this.drawerLayout.openDrawer(fragmentContainerView);
+ }
+ this.drawerLayout.post(new Runnable() {
+ @Override
+ public void run() {
+ drawerToggle.syncState();
}
+ });
+ this.drawerLayout.setDrawerListener(drawerToggle);
+ }
- private void selectItem(int position) {
- currentSelectedPosition = position;
- if (drawerListView != null) {
- drawerListView.setItemChecked(position, true);
- }
- if (drawerLayout != null) {
- drawerLayout.closeDrawer(fragmentContainerView);
- }
-
- Activity activity = getActivity();
- if (activity != null && activity instanceof NavigationDrawerActivity) {
- NavigationDrawerActivity navActivity = (NavigationDrawerActivity) activity;
- navActivity.onNavigationDrawerItemSelected(position);
- }
- }
+ private void selectItem(int position) {
+ currentSelectedPosition = position;
+ if (drawerListView != null) {
+ drawerListView.setItemChecked(position, true);
+ }
+ if (drawerLayout != null) {
+ drawerLayout.closeDrawer(fragmentContainerView);
+ }
+
+ Activity activity = getActivity();
+ if (activity != null && activity instanceof NavigationDrawerActivity) {
+ NavigationDrawerActivity navActivity = (NavigationDrawerActivity) activity;
+ navActivity.onNavigationDrawerItemSelected(position);
+ }
+ }
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putInt(STATE_SELECTED_POSITION, currentSelectedPosition);
- }
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(STATE_SELECTED_POSITION, currentSelectedPosition);
+ }
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- drawerToggle.onConfigurationChanged(newConfig);
- }
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ drawerToggle.onConfigurationChanged(newConfig);
+ }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (drawerToggle.onOptionsItemSelected(item)) {
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (drawerToggle.onOptionsItemSelected(item)) {
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SimpleMapActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SimpleMapActivity.java
new file mode 100644
index 0000000000..7e04b95e20
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SimpleMapActivity.java
@@ -0,0 +1,86 @@
+package com.mapbox.mapboxsdk.testapp.activity.maplayout;
+
+import android.os.Bundle;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
+
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.testapp.R;
+
+public class SimpleMapActivity extends AppCompatActivity {
+
+ private MapView mapView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_map_simple);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SurfaceViewMediaControlActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SurfaceViewMediaControlActivity.java
deleted file mode 100644
index 43b4264661..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SurfaceViewMediaControlActivity.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.activity.maplayout;
-
-import android.content.Context;
-import android.opengl.GLSurfaceView;
-import android.os.Bundle;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.widget.FrameLayout;
-
-import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.R;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-public class SurfaceViewMediaControlActivity extends AppCompatActivity implements OnMapReadyCallback {
-
- private MapView mapView;
- private MapboxMap mapboxMap;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_surfaceview_mediacontrols);
-
- final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
-
- // add another SurfaceView to the Layout
- FrameLayout container = (FrameLayout) findViewById(R.id.container);
- GLSurfaceView mediaControlSurfaceView = new ClearGLSurfaceView(this);
- mediaControlSurfaceView.setZOrderMediaOverlay(true);
- container.addView(mediaControlSurfaceView);
- }
-
- @Override
- public void onMapReady(MapboxMap mapboxMap) {
- this.mapboxMap = mapboxMap;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_padding, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- class ClearGLSurfaceView extends GLSurfaceView {
-
- private ClearRenderer renderer;
-
- public ClearGLSurfaceView(Context context) {
- super(context);
- renderer = new ClearRenderer();
- setRenderer(renderer);
- }
-
- public boolean onTouchEvent(final MotionEvent event) {
- queueEvent(new Runnable() {
- public void run() {
- renderer.setColor(event.getRawX() / getWidth(),
- event.getRawY() / getHeight(), 1.0f);
- }
- });
- return true;
- }
- }
-
- class ClearRenderer implements GLSurfaceView.Renderer {
-
- private float red;
- private float green;
- private float blue;
-
- public void onSurfaceCreated(GL10 gl, EGLConfig config) {
- // Do nothing special.
- }
-
- public void onSurfaceChanged(GL10 gl, int width, int height) {
- gl.glViewport(0, 0, width, height);
- }
-
- public void onDrawFrame(GL10 gl) {
- gl.glClearColor(red, green, blue, 1.0f);
- gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
- }
-
- public void setColor(float red, float green, float blue) {
- this.red = red;
- this.green = green;
- this.blue = blue;
- }
- }
-}
-
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VideoViewActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VideoViewActivity.java
deleted file mode 100644
index 96637fae87..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VideoViewActivity.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.activity.maplayout;
-
-import android.media.MediaPlayer;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.MenuItem;
-import android.widget.VideoView;
-
-import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.R;
-
-import static android.media.MediaPlayer.OnPreparedListener;
-
-public class VideoViewActivity extends AppCompatActivity {
-
- private MapView mapView;
- private MapboxMap mapboxMap;
- private VideoView videoView;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_video_view);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- // Setup the video
- videoView = (VideoView) findViewById(R.id.video_view);
- videoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.sea_waves));
- videoView.start();
-
- // Used to repeat the video.
- videoView.setOnPreparedListener(new OnPreparedListener() {
- @Override
- public void onPrepared(MediaPlayer mediaPlayer) {
- mediaPlayer.setLooping(true);
- }
- });
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap mapboxMap) {
- VideoViewActivity.this.mapboxMap = mapboxMap;
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/navigation/CarDrivingActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/navigation/CarDrivingActivity.java
index a40ec0534c..4bb6bc5f39 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/navigation/CarDrivingActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/navigation/CarDrivingActivity.java
@@ -32,158 +32,170 @@ import com.mapbox.mapboxsdk.testapp.R;
public class CarDrivingActivity extends AppCompatActivity implements MapboxMap.OnMyLocationChangeListener {
- private static final int PERMISSIONS_LOCATION = 0;
+ private static final int PERMISSIONS_LOCATION = 0;
- private MapView mapView;
- private MapboxMap mapboxMap;
- private Location location;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private Location location;
- @Override
- protected void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_car_driving);
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_car_driving);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- CarDrivingActivity.this.mapboxMap = mapboxMap;
-
- // view settings
- MyLocationViewSettings settings = mapboxMap.getMyLocationViewSettings();
- settings.setPadding(0, getWindow().getDecorView().getMeasuredHeight() / 3, 0, 0);
-
- // get car
- Drawable car = ResourcesCompat.getDrawable(getResources(), R.drawable.ic_taxi_top_small, getTheme());
- settings.setForegroundTintColor(Color.TRANSPARENT);
- settings.setForegroundDrawable(car, car);
-
- // remove accuracy circle
- settings.setAccuracyAlpha(0);
-
- // disable dismissal when a gesture occurs
- TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
- trackingSettings.setDismissLocationTrackingOnGesture(false);
- trackingSettings.setDismissBearingTrackingOnGesture(false);
-
- mapboxMap.setOnMyLocationChangeListener(CarDrivingActivity.this);
-
- if (savedInstanceState == null) {
- toggleGps(true);
- }
- }
- });
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @UiThread
- public void toggleGps(boolean enableGps) {
- if (enableGps) {
- if ((ContextCompat.checkSelfPermission(this,
- Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
- || (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED)) {
- ActivityCompat.requestPermissions(this, new String[]{
- Manifest.permission.ACCESS_COARSE_LOCATION,
- Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
- } else {
- enableLocation(true);
- }
- } else {
- enableLocation(false);
- }
- }
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ CarDrivingActivity.this.mapboxMap = mapboxMap;
- private void enableLocation(boolean enabled) {
- if (enabled) {
- mapboxMap.setMyLocationEnabled(true);
- Location location = mapboxMap.getMyLocation();
- if (location != null) {
- setInitialPosition(new LatLng(location));
- }
- } else {
- mapboxMap.setMyLocationEnabled(false);
- }
- }
+ // view settings
+ MyLocationViewSettings settings = mapboxMap.getMyLocationViewSettings();
+ settings.setPadding(0, getWindow().getDecorView().getMeasuredHeight() / 3, 0, 0);
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- if (requestCode == PERMISSIONS_LOCATION) {
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- enableLocation(true);
- }
- }
- }
+ // get car
+ Drawable car = ResourcesCompat.getDrawable(getResources(), R.drawable.ic_taxi_top_small, getTheme());
+ settings.setForegroundTintColor(Color.TRANSPARENT);
+ settings.setForegroundDrawable(car, car);
- private void setInitialPosition(LatLng latLng) {
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
- new CameraPosition.Builder().target(latLng).zoom(15).tilt(20f).build()));
- mapboxMap.setMyLocationEnabled(true);
+ // remove accuracy circle
+ settings.setAccuracyAlpha(0);
+ // disable dismissal when a gesture occurs
TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
- trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- trackingSettings.setMyBearingTrackingMode(MyBearingTracking.GPS);
- }
+ trackingSettings.setDismissLocationTrackingOnGesture(false);
+ trackingSettings.setDismissBearingTrackingOnGesture(false);
- @Override
- public void onMyLocationChange(@Nullable Location location) {
- if (location != null) {
- if (this.location == null) {
- // initial location to reposition map
- setInitialPosition(new LatLng(location));
- }
- this.location = location;
- }
- }
+ mapboxMap.setOnMyLocationChangeListener(CarDrivingActivity.this);
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
+ if (savedInstanceState == null) {
+ toggleGps(true);
+ }
+ }
+ });
+ }
+
+ @UiThread
+ public void toggleGps(boolean enableGps) {
+ if (enableGps) {
+ if ((ContextCompat.checkSelfPermission(this,
+ Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
+ || (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED)) {
+ ActivityCompat.requestPermissions(this, new String[] {
+ Manifest.permission.ACCESS_COARSE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
+ } else {
+ enableLocation(true);
+ }
+ } else {
+ enableLocation(false);
}
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ }
+
+ private void enableLocation(boolean enabled) {
+ if (enabled) {
+ mapboxMap.setMyLocationEnabled(true);
+ Location location = mapboxMap.getMyLocation();
+ if (location != null) {
+ setInitialPosition(new LatLng(location));
+ }
+ } else {
+ mapboxMap.setMyLocationEnabled(false);
}
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ if (requestCode == PERMISSIONS_LOCATION) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ enableLocation(true);
+ }
}
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ }
+
+ private void setInitialPosition(LatLng latLng) {
+ mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder().target(latLng).zoom(15).tilt(20f).build()));
+ mapboxMap.setMyLocationEnabled(true);
+
+ TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
+ trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
+ trackingSettings.setMyBearingTrackingMode(MyBearingTracking.GPS);
+ }
+
+ @Override
+ public void onMyLocationChange(@Nullable Location location) {
+ if (location != null) {
+ if (this.location == null) {
+ // initial location to reposition map
+ setInitialPosition(new LatLng(location));
+ }
+ this.location = location;
}
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/navigation/LocationPickerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/navigation/LocationPickerActivity.java
index be5498babb..8fb53645a1 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/navigation/LocationPickerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/navigation/LocationPickerActivity.java
@@ -14,7 +14,9 @@ import android.support.v4.app.ActivityCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MenuItem;
@@ -42,12 +44,12 @@ import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.model.annotations.PulseMarkerView;
import com.mapbox.mapboxsdk.testapp.model.annotations.PulseMarkerViewOptions;
-import com.mapbox.services.commons.ServicesException;
+import com.mapbox.services.api.ServicesException;
import com.mapbox.services.commons.models.Position;
-import com.mapbox.services.geocoding.v5.GeocodingCriteria;
-import com.mapbox.services.geocoding.v5.MapboxGeocoding;
-import com.mapbox.services.geocoding.v5.models.CarmenFeature;
-import com.mapbox.services.geocoding.v5.models.GeocodingResponse;
+import com.mapbox.services.api.geocoding.v5.GeocodingCriteria;
+import com.mapbox.services.api.geocoding.v5.MapboxGeocoding;
+import com.mapbox.services.api.geocoding.v5.models.CarmenFeature;
+import com.mapbox.services.api.geocoding.v5.models.GeocodingResponse;
import java.util.List;
@@ -59,412 +61,417 @@ import retrofit2.Response;
* Sample Activity to show a typical location picker use case
*/
public class LocationPickerActivity extends AppCompatActivity {
- private static final String TAG = "LocationPickerActivity";
- private static final int REQUEST_PERMISSIONS = 101;
-
- private MapView mapView;
- private MapboxMap mapboxMap;
-
- private ImageView dropPinView;
- private Marker addressPin;
- private ImageButton clearDisplayViewButton;
- private MarkerView userMarker;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_location_picker);
-
- setupActionBar();
-
- //Initialize map as normal
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
-
- //Create ui elements
- createDropPin();
- createSelectLocationButton();
- createClearSelectionButton();
-
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- //Store for later
- mapboxMap = map;
-
- //Add user marker
- mapboxMap.getMarkerViewManager().addMarkerViewAdapter(
- new PulseMarkerViewAdapter(LocationPickerActivity.this));
- userMarker = createCustomUserMarker(new LatLng(0, 0));
-
- //Fix the focal point to the center of the map
- PointF focalPoint = new PointF(
- (mapView.getX() + mapView.getWidth() / 2), (mapView.getY() + mapView.getHeight() / 2));
- mapboxMap.getUiSettings().setFocalPoint(focalPoint);
-
- //Track camera updates to animate the user location views
- trackUserLocationView(userMarker);
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
-
- //Check permissions
- if (arePermissionsGranted()) {
- mapView.getMapAsync(new OnMapReadyCallback() {
-
- @Override
- public void onMapReady(final MapboxMap mapboxMap) {
- //Get the user's location
- final LocationServices locationServices = LocationServices.getLocationServices(getApplicationContext());
-
- Location location = locationServices.getLastLocation();
- if (location != null) {
- zoomInOn(location);
- userMarker.setPosition(new LatLng(location));
- } else {
- final ProgressDialog loadingDialog = ProgressDialog.show(
- LocationPickerActivity.this, "Loading", "Getting user location", false);
- locationServices.addLocationListener(new LocationListener() {
- @Override
- public void onLocationChanged(@Nullable Location location) {
- //Move the camera to the user
- if (location != null) {
- zoomInOn(location);
- userMarker.setPosition(new LatLng(location));
- locationServices.removeLocationListener(this);
- loadingDialog.hide();
- }
- }
- });
- }
-
- locationServices.toggleGPS(true);
- }
- });
- }
+ private static final int REQUEST_PERMISSIONS = 101;
+
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+
+ private ImageView dropPinView;
+ private Marker addressPin;
+ private ImageButton clearDisplayViewButton;
+ private MarkerView userMarker;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_location_picker);
+
+ setupActionBar();
+
+ //Initialize map as normal
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+
+ //Create ui elements
+ createDropPin();
+ createSelectLocationButton();
+ createClearSelectionButton();
+
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap map) {
+ //Store for later
+ mapboxMap = map;
+
+ //Add user marker
+ mapboxMap.getMarkerViewManager().addMarkerViewAdapter(
+ new PulseMarkerViewAdapter(LocationPickerActivity.this));
+ userMarker = createCustomUserMarker(new LatLng(0, 0));
+
+ //Fix the focal point to the center of the map
+ PointF focalPoint = new PointF(
+ (mapView.getX() + mapView.getWidth() / 2), (mapView.getY() + mapView.getHeight() / 2));
+ mapboxMap.getUiSettings().setFocalPoint(focalPoint);
+
+ //Track camera updates to animate the user location views
+ trackUserLocationView(userMarker);
+ }
+ });
+ }
+
+ private void zoomInOn(Location location) {
+ //Move the camera to the user
+ if (location != null) {
+ mapboxMap.setCameraPosition(new CameraPosition.Builder()
+ .target(new LatLng(location))
+ .zoom(16)
+ .bearing(0)
+ .tilt(0)
+ .build());
}
+ }
- private void zoomInOn(Location location) {
- //Move the camera to the user
- if (location != null) {
- mapboxMap.setCameraPosition(new CameraPosition.Builder()
- .target(new LatLng(location))
- .zoom(16)
- .bearing(0)
- .tilt(0)
- .build());
- }
- }
+ /**
+ * Tracks the camera to animate the marker when overlapping with the picker.
+ * Makes sure the marker actually points to the user's position by tracking it.
+ */
+ private void trackUserLocationView(final MarkerView markerView) {
+ final float circleDiameterSize = getResources().getDimension(R.dimen.circle_size);
- /**
- * Tracks the camera to animate the marker when overlapping with the picker.
- * Makes sure the marker actually points to the user's position by tracking it.
- */
- private void trackUserLocationView(final MarkerView markerView) {
- final float circleDiameterSize = getResources().getDimension(R.dimen.circle_size);
+ //Track camera changes to check for overlap
+ mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
- //Track camera changes to check for overlap
- mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
+ private Animation pulseAnimation;
- private Animation pulseAnimation;
-
- @Override
- public void onCameraChange(CameraPosition position) {
- if (markerView == null) {
- return;
- }
+ @Override
+ public void onCameraChange(CameraPosition position) {
+ if (markerView == null) {
+ return;
+ }
- //Make drop pin visible, if it wasn't already
- showDropPin();
-
- //Get the distance from the tip of the location picker to the MarkerView
- double distance = getLocationPickerLocation().distanceTo(markerView.getPosition());
-
- //If closeby, animate, otherwise, stop animation
- View view = mapboxMap.getMarkerViewManager().getView(markerView);
- if (view != null) {
- View backgroundView = view.findViewById(R.id.background_imageview);
- if (pulseAnimation == null && distance < 0.5f * circleDiameterSize) {
- pulseAnimation = AnimationUtils.loadAnimation(LocationPickerActivity.this, R.anim.pulse);
- pulseAnimation.setRepeatCount(Animation.INFINITE);
- pulseAnimation.setRepeatMode(Animation.RESTART);
- backgroundView.startAnimation(pulseAnimation);
- } else if (pulseAnimation != null && distance >= 0.5f * circleDiameterSize) {
- backgroundView.clearAnimation();
- pulseAnimation = null;
- }
- }
- }
- });
-
- //Track location updates to move the user marker
- LocationServices.getLocationServices(getApplicationContext()).addLocationListener(new LocationListener() {
- @Override
- public void onLocationChanged(Location location) {
- if (location != null && markerView != null) {
- markerView.setPosition(new LatLng(location));
- }
- }
- });
- }
+ //Make drop pin visible, if it wasn't already
+ showDropPin();
- private MarkerView createCustomUserMarker(LatLng markerPosition) {
- return mapboxMap.addMarker(new PulseMarkerViewOptions()
- .icon(IconFactory.getInstance(getApplicationContext()).fromResource(R.drawable.ic_my_location_24dp))
- .position(markerPosition)
- );
- }
+ //Get the distance from the tip of the location picker to the MarkerView
+ double distance = getLocationPickerLocation().distanceTo(markerView.getPosition());
- private void createClearSelectionButton() {
- clearDisplayViewButton = (ImageButton) findViewById(R.id.clearDisplayViewButton);
- clearDisplayViewButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- removeAddressPin();
- hide(clearDisplayViewButton);
- showDropPin();
- }
- });
+ //If closeby, animate, otherwise, stop animation
+ View view = mapboxMap.getMarkerViewManager().getView(markerView);
+ if (view != null) {
+ View backgroundView = view.findViewById(R.id.background_imageview);
+ if (pulseAnimation == null && distance < 0.5f * circleDiameterSize) {
+ pulseAnimation = AnimationUtils.loadAnimation(LocationPickerActivity.this, R.anim.pulse);
+ pulseAnimation.setRepeatCount(Animation.INFINITE);
+ pulseAnimation.setRepeatMode(Animation.RESTART);
+ backgroundView.startAnimation(pulseAnimation);
+ } else if (pulseAnimation != null && distance >= 0.5f * circleDiameterSize) {
+ backgroundView.clearAnimation();
+ pulseAnimation = null;
+ }
+ }
+ }
+ });
+
+ //Track location updates to move the user marker
+ LocationServices.getLocationServices(getApplicationContext()).addLocationListener(new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ if (location != null && markerView != null) {
+ markerView.setPosition(new LatLng(location));
+ }
+ }
+ });
+ }
+
+ private MarkerView createCustomUserMarker(LatLng markerPosition) {
+ return mapboxMap.addMarker(new PulseMarkerViewOptions()
+ .icon(IconFactory.getInstance(getApplicationContext()).fromResource(R.drawable.ic_my_location_24dp))
+ .position(markerPosition)
+ );
+ }
+
+ private void createClearSelectionButton() {
+ clearDisplayViewButton = (ImageButton) findViewById(R.id.clearDisplayViewButton);
+ clearDisplayViewButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ removeAddressPin();
+ hide(clearDisplayViewButton);
+ showDropPin();
+ }
+ });
+ }
+
+ private void createSelectLocationButton() {
+ Button selectLocationButton = (Button) findViewById(R.id.selectLocationButton);
+ //noinspection ConstantConditions
+ selectLocationButton.setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Timber.i("Location Selected!");
+ if (mapboxMap != null) {
+ //Control button's state
+ clearDisplayViewButton.setVisibility(View.VISIBLE);
+ dropPinView.setVisibility(View.INVISIBLE);
+
+ //Get position for the drop pin
+ LatLng position = getLocationPickerLocation();
+
+ //Show the address pin (result)
+ showAddressPin(position);
+
+ //Get the address for that location and update the marker
+ geocode(position, new GeocodeCallbacks() {
+ @Override
+ public void onResult(String result) {
+ updateAddressPin(result);
+ }
+
+ @Override
+ public void onFailure(Throwable failure) {
+ showFeedbackMessage("Could not retrieve address: " + failure.getMessage());
+ }
+ });
+ }
+ }
+ }
+ );
+ }
+
+ private void createDropPin() {
+ float density = getResources().getDisplayMetrics().density;
+
+ dropPinView = new ImageView(this);
+ dropPinView.setImageResource(R.drawable.ic_droppin_24dp);
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
+ params.bottomMargin = (int) (12 * density);
+ dropPinView.setLayoutParams(params);
+
+ mapView.addView(dropPinView);
+ }
+
+ private void showDropPin() {
+ if (dropPinView != null && dropPinView.getVisibility() != View.VISIBLE) {
+ dropPinView.setVisibility(View.VISIBLE);
}
+ }
- private void createSelectLocationButton() {
- Button selectLocationButton = (Button) findViewById(R.id.selectLocationButton);
- //noinspection ConstantConditions
- selectLocationButton.setOnClickListener(
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Log.i(TAG, "Location Selected!");
- if (mapboxMap != null) {
- //Control button's state
- clearDisplayViewButton.setVisibility(View.VISIBLE);
- dropPinView.setVisibility(View.INVISIBLE);
-
- //Get position for the drop pin
- LatLng position = getLocationPickerLocation();
-
- //Show the address pin (result)
- showAddressPin(position);
-
- //Get the address for that location and update the marker
- geocode(position, new GeocodeCallbacks() {
- @Override
- public void onResult(String result) {
- updateAddressPin(result);
- }
-
- @Override
- public void onFailure(Throwable failure) {
- showFeedbackMessage("Could not retrieve address: " + failure.getMessage());
- }
- });
- }
- }
- }
- );
+ private void hide(View view) {
+ if (view != null) {
+ view.setVisibility(View.INVISIBLE);
}
+ }
- private void createDropPin() {
- float density = getResources().getDisplayMetrics().density;
-
- dropPinView = new ImageView(this);
- dropPinView.setImageResource(R.drawable.ic_droppin_24dp);
- FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
- params.bottomMargin = (int) (12 * density);
- dropPinView.setLayoutParams(params);
+ private void setupActionBar() {
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- mapView.addView(dropPinView);
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
-
- private void showDropPin() {
- if (dropPinView != null && dropPinView.getVisibility() != View.VISIBLE) {
- dropPinView.setVisibility(View.VISIBLE);
+ }
+
+ /**
+ * Get address for the given location
+ */
+ private void geocode(LatLng point, final GeocodeCallbacks callbacks) {
+ try {
+ //Create Geocoding client
+ MapboxGeocoding client = new MapboxGeocoding.Builder()
+ .setAccessToken(getString(R.string.mapbox_access_token))
+ .setCoordinates(Position.fromCoordinates(point.getLongitude(), point.getLatitude()))
+ .setGeocodingType(GeocodingCriteria.TYPE_ADDRESS)
+ .build();
+
+ //Place the request
+ client.enqueueCall(new Callback<GeocodingResponse>() {
+ @Override
+ public void onResponse(Call<GeocodingResponse> call, Response<GeocodingResponse> response) {
+
+ List<CarmenFeature> results = response.body().getFeatures();
+ String address = null;
+ if (results.size() > 0) {
+ CarmenFeature feature = results.get(0);
+ address = feature.getAddress() + " " + feature.getText();
+ Timber.i("address " + address);
+ } else {
+ showFeedbackMessage("No results for search.");
+ }
+
+ callbacks.onResult(address);
}
- }
- private void hide(View view) {
- if (view != null) {
- view.setVisibility(View.INVISIBLE);
+ @Override
+ public void onFailure(Call<GeocodingResponse> call, Throwable throwable) {
+ Timber.e("Geocoding Failure: " + throwable.getMessage());
+ callbacks.onFailure(throwable);
}
+ });
+ } catch (ServicesException servicesException) {
+ Timber.e("Error geocoding: " + servicesException.toString());
+ callbacks.onFailure(servicesException);
}
-
- private void setupActionBar() {
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
+ }
+
+ private LatLng getLocationPickerLocation() {
+ return mapboxMap.getProjection().fromScreenLocation(
+ new PointF(dropPinView.getLeft() + (dropPinView.getWidth() / 2), dropPinView.getBottom())
+ );
+ }
+
+ private Marker showAddressPin(LatLng position) {
+ if (addressPin != null) {
+ //Remove previous pin
+ removeAddressPin();
}
- /**
- * Get address for the given location
- */
- private void geocode(LatLng point, final GeocodeCallbacks callbacks) {
- try {
- //Create Geocoding client
- MapboxGeocoding client = new MapboxGeocoding.Builder()
- .setAccessToken(getString(R.string.mapbox_access_token))
- .setCoordinates(Position.fromCoordinates(point.getLongitude(), point.getLatitude()))
- .setGeocodingType(GeocodingCriteria.TYPE_ADDRESS)
- .build();
-
- //Place the request
- client.enqueueCall(new Callback<GeocodingResponse>() {
- @Override
- public void onResponse(Call<GeocodingResponse> call, Response<GeocodingResponse> response) {
-
- List<CarmenFeature> results = response.body().getFeatures();
- String address = null;
- if (results.size() > 0) {
- CarmenFeature feature = results.get(0);
- address = feature.getAddress() + " " + feature.getText();
- Log.i(TAG, "address " + address);
- } else {
- showFeedbackMessage("No results for search.");
- }
-
- callbacks.onResult(address);
- }
+ //Create new one
+ addressPin = mapboxMap.addMarker(new MarkerViewOptions().title("Loading address...").position(position));
+ mapboxMap.selectMarker(addressPin);
+ return addressPin;
+ }
- @Override
- public void onFailure(Call<GeocodingResponse> call, Throwable throwable) {
- Log.e(TAG, "Geocoding Failure: " + throwable.getMessage());
- callbacks.onFailure(throwable);
- }
- });
- } catch (ServicesException servicesException) {
- Log.e(TAG, "Error geocoding: " + servicesException.toString());
- callbacks.onFailure(servicesException);
- }
+ private void removeAddressPin() {
+ if (mapboxMap != null && addressPin != null) {
+ mapboxMap.removeMarker(addressPin);
}
+ }
- private LatLng getLocationPickerLocation() {
- return mapboxMap.getProjection().fromScreenLocation(
- new PointF(dropPinView.getLeft() + (dropPinView.getWidth() / 2), dropPinView.getBottom())
- );
+ private void updateAddressPin(@Nullable String address) {
+ if (addressPin != null) {
+ addressPin.setTitle(address == null ? "No address found" : address);
}
-
- private Marker showAddressPin(LatLng position) {
- if (addressPin != null) {
- //Remove previous pin
- removeAddressPin();
- }
-
- //Create new one
- addressPin = mapboxMap.addMarker(new MarkerViewOptions().title("Loading address...").position(position));
- mapboxMap.selectMarker(addressPin);
- return addressPin;
+ }
+
+ private void showFeedbackMessage(String message) {
+ Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
+ }
+
+ private boolean arePermissionsGranted() {
+ if (Build.VERSION.SDK_INT >= 23
+ && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
+ && checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+ Timber.i("Requesting permissions");
+ ActivityCompat.requestPermissions(this, new String[] {
+ Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSIONS);
+ return false;
}
+ Timber.i("Permissions already granted");
+ return true;
+ }
- private void removeAddressPin() {
- if (mapboxMap != null && addressPin != null) {
- mapboxMap.removeMarker(addressPin);
- }
- }
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
- private void updateAddressPin(@Nullable String address) {
- if (addressPin != null) {
- addressPin.setTitle(address == null ? "No address found" : address);
- }
- }
+ //Check permissions
+ if (arePermissionsGranted()) {
+ mapView.getMapAsync(new OnMapReadyCallback() {
- private void showFeedbackMessage(String message) {
- Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
- }
+ @Override
+ public void onMapReady(final MapboxMap mapboxMap) {
+ //Get the user's location
+ final LocationServices locationServices = LocationServices.getLocationServices(getApplicationContext());
+
+ Location location = locationServices.getLastLocation();
+ if (location != null) {
+ zoomInOn(location);
+ userMarker.setPosition(new LatLng(location));
+ } else {
+ final ProgressDialog loadingDialog = ProgressDialog.show(
+ LocationPickerActivity.this, "Loading", "Getting user location", false);
+ locationServices.addLocationListener(new LocationListener() {
+ @Override
+ public void onLocationChanged(@Nullable Location location) {
+ //Move the camera to the user
+ if (location != null) {
+ zoomInOn(location);
+ userMarker.setPosition(new LatLng(location));
+ locationServices.removeLocationListener(this);
+ loadingDialog.hide();
+ }
+ }
+ });
+ }
- private boolean arePermissionsGranted() {
- if (Build.VERSION.SDK_INT >= 23
- && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
- && checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
- Log.i(TAG, "Requesting permissions");
- ActivityCompat.requestPermissions(this, new String[]{
- Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSIONS);
- return false;
+ locationServices.toggleGPS(true);
}
- Log.i(TAG, "Permissions already granted");
- return true;
+ });
}
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
+ /**
+ * Custom MarkerViewAdapter for the pulsing marker
+ */
+ private static class PulseMarkerViewAdapter extends MapboxMap.MarkerViewAdapter<PulseMarkerView> {
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ private LayoutInflater inflater;
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ public PulseMarkerViewAdapter(@NonNull Context context) {
+ super(context);
+ this.inflater = LayoutInflater.from(context);
}
+ @Nullable
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ public View getView(@NonNull PulseMarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
+ ViewHolder viewHolder;
+ if (convertView == null) {
+ viewHolder = new ViewHolder();
+ convertView = inflater.inflate(R.layout.view_pulse_marker, parent, false);
+ viewHolder.foregroundImageView = (ImageView) convertView.findViewById(R.id.foreground_imageView);
+ viewHolder.backgroundImageView = (ImageView) convertView.findViewById(R.id.background_imageview);
+ convertView.setTag(viewHolder);
+ }
+ return convertView;
}
- /**
- * Custom MarkerViewAdapter for the pulsing marker
- */
- private static class PulseMarkerViewAdapter extends MapboxMap.MarkerViewAdapter<PulseMarkerView> {
-
- private LayoutInflater inflater;
-
- public PulseMarkerViewAdapter(@NonNull Context context) {
- super(context);
- this.inflater = LayoutInflater.from(context);
- }
-
- @Nullable
- @Override
- public View getView(@NonNull PulseMarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
- ViewHolder viewHolder;
- if (convertView == null) {
- viewHolder = new ViewHolder();
- convertView = inflater.inflate(R.layout.view_pulse_marker, parent, false);
- viewHolder.foregroundImageView = (ImageView) convertView.findViewById(R.id.foreground_imageView);
- viewHolder.backgroundImageView = (ImageView) convertView.findViewById(R.id.background_imageview);
- convertView.setTag(viewHolder);
- }
- return convertView;
- }
-
- private static class ViewHolder {
- ImageView foregroundImageView;
- ImageView backgroundImageView;
- }
+ private static class ViewHolder {
+ ImageView foregroundImageView;
+ ImageView backgroundImageView;
}
+ }
- private interface GeocodeCallbacks {
- void onResult(String result);
+ private interface GeocodeCallbacks {
+ void onResult(String result);
- void onFailure(Throwable failure);
- }
+ void onFailure(Throwable failure);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
index e9dd9dc5f4..e2eda0e6b1 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
@@ -6,14 +6,13 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
-import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;
-import com.mapbox.mapboxsdk.MapboxAccountManager;
+import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
@@ -35,309 +34,319 @@ import com.mapbox.mapboxsdk.testapp.utils.OfflineUtils;
import java.util.ArrayList;
-public class OfflineActivity extends AppCompatActivity
- implements OfflineDownloadRegionDialog.DownloadRegionDialogListener {
-
- private static final String LOG_TAG = "OfflineActivity";
-
- // JSON encoding/decoding
- public static final String JSON_CHARSET = "UTF-8";
- public static final String JSON_FIELD_REGION_NAME = "FIELD_REGION_NAME";
-
- /*
- * UI elements
- */
- private MapView mapView;
- private MapboxMap mapboxMap;
- private ProgressBar progressBar;
- private Button downloadRegion;
- private Button listRegions;
-
- private boolean isEndNotified;
-
- /*
- * Offline objects
- */
- private OfflineManager offlineManager;
- private OfflineRegion offlineRegion;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_offline);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- // You can use MapboxAccountManager.setConnected(Boolean) to manually set the connectivity
- // state of your app. This will override any checks performed via the ConnectivityManager.
- //MapboxAccountManager.getInstance().setConnected(false);
- Boolean connected = MapboxAccountManager.getInstance().isConnected();
- Log.d(LOG_TAG, String.format(MapboxConstants.MAPBOX_LOCALE,
- "MapboxAccountManager is connected: %b", connected));
-
- // Set up map
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.setStyleUrl(Style.MAPBOX_STREETS);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- Log.d(LOG_TAG, "Map is ready");
- OfflineActivity.this.mapboxMap = mapboxMap;
-
- // Set initial position to UNHQ in NYC
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
- new CameraPosition.Builder()
- .target(new LatLng(40.749851, -73.967966))
- .zoom(14)
- .bearing(0)
- .tilt(0)
- .build()));
- }
- });
-
- // The progress bar
- progressBar = (ProgressBar) findViewById(R.id.progress_bar);
-
- // Set up button listeners
- downloadRegion = (Button) findViewById(R.id.button_download_region);
- downloadRegion.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- handleDownloadRegion();
- }
- });
-
- listRegions = (Button) findViewById(R.id.button_list_regions);
- listRegions.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- handleListRegions();
- }
- });
-
- // Set up the OfflineManager
- offlineManager = OfflineManager.getInstance(this);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
+import timber.log.Timber;
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+public class OfflineActivity extends AppCompatActivity
+ implements OfflineDownloadRegionDialog.DownloadRegionDialogListener {
+
+ // JSON encoding/decoding
+ public static final String JSON_CHARSET = "UTF-8";
+ public static final String JSON_FIELD_REGION_NAME = "FIELD_REGION_NAME";
+
+ // Style URL
+ public static final String STYLE_URL = Style.MAPBOX_STREETS;
+
+ /*
+ * UI elements
+ */
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private ProgressBar progressBar;
+ private Button downloadRegion;
+ private Button listRegions;
+
+ private boolean isEndNotified;
+
+ /*
+ * Offline objects
+ */
+ private OfflineManager offlineManager;
+ private OfflineRegion offlineRegion;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_offline);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ // You can use Mapbox.setConnected(Boolean) to manually set the connectivity
+ // state of your app. This will override any checks performed via the ConnectivityManager.
+ //Mapbox.getInstance().setConnected(false);
+ Boolean connected = Mapbox.isConnected();
+ Timber.d(String.format(MapboxConstants.MAPBOX_LOCALE,
+ "Mapbox is connected: %b", connected));
+
+ // Set up map
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.setStyleUrl(STYLE_URL);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ Timber.d("Map is ready");
+ OfflineActivity.this.mapboxMap = mapboxMap;
+
+ // Set initial position to UNHQ in NYC
+ mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .target(new LatLng(40.749851, -73.967966))
+ .zoom(14)
+ .bearing(0)
+ .tilt(0)
+ .build()));
+ }
+ });
+
+ // The progress bar
+ progressBar = (ProgressBar) findViewById(R.id.progress_bar);
+
+ // Set up button listeners
+ downloadRegion = (Button) findViewById(R.id.button_download_region);
+ downloadRegion.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ handleDownloadRegion();
+ }
+ });
+
+ listRegions = (Button) findViewById(R.id.button_list_regions);
+ listRegions.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ handleListRegions();
+ }
+ });
+
+ // Set up the OfflineManager
+ offlineManager = OfflineManager.getInstance(this);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ }
+
+ /*
+ * Buttons logic
+ */
+ private void handleDownloadRegion() {
+ Timber.d("handleDownloadRegion");
+
+ // Show dialog
+ OfflineDownloadRegionDialog offlineDownloadRegionDialog = new OfflineDownloadRegionDialog();
+ offlineDownloadRegionDialog.show(getSupportFragmentManager(), "download");
+ }
+
+ private void handleListRegions() {
+ Timber.d("handleListRegions");
+
+ // Query the DB asynchronously
+ offlineManager.listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {
+ @Override
+ public void onList(OfflineRegion[] offlineRegions) {
+ // Check result
+ if (offlineRegions == null || offlineRegions.length == 0) {
+ Toast.makeText(OfflineActivity.this, "You have no regions yet.", Toast.LENGTH_SHORT).show();
+ return;
}
- }
- /*
- * Buttons logic
- */
+ // Get regions info
+ ArrayList<String> offlineRegionsNames = new ArrayList<>();
+ for (OfflineRegion offlineRegion : offlineRegions) {
+ offlineRegionsNames.add(OfflineUtils.convertRegionName(offlineRegion.getMetadata()));
+ }
- private void handleDownloadRegion() {
- Log.d(LOG_TAG, "handleDownloadRegion");
+ // Create args
+ Bundle args = new Bundle();
+ args.putStringArrayList(OfflineListRegionsDialog.ITEMS, offlineRegionsNames);
// Show dialog
- OfflineDownloadRegionDialog offlineDownloadRegionDialog = new OfflineDownloadRegionDialog();
- offlineDownloadRegionDialog.show(getSupportFragmentManager(), "download");
+ OfflineListRegionsDialog offlineListRegionsDialog = new OfflineListRegionsDialog();
+ offlineListRegionsDialog.setArguments(args);
+ offlineListRegionsDialog.show(getSupportFragmentManager(), "list");
+ }
+
+ @Override
+ public void onError(String error) {
+ Timber.e("Error: " + error);
+ }
+ });
+ }
+
+ /*
+ * Dialogs
+ */
+ @Override
+ public void onDownloadRegionDialogPositiveClick(final String regionName) {
+ if (TextUtils.isEmpty(regionName)) {
+ Toast.makeText(OfflineActivity.this, "Region name cannot be empty.", Toast.LENGTH_SHORT).show();
+ return;
}
- private void handleListRegions() {
- Log.d(LOG_TAG, "handleListRegions");
-
- // Query the DB asynchronously
- offlineManager.listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {
- @Override
- public void onList(OfflineRegion[] offlineRegions) {
- // Check result
- if (offlineRegions == null || offlineRegions.length == 0) {
- Toast.makeText(OfflineActivity.this, "You have no regions yet.", Toast.LENGTH_SHORT).show();
- return;
- }
-
- // Get regions info
- ArrayList<String> offlineRegionsNames = new ArrayList<>();
- for (OfflineRegion offlineRegion : offlineRegions) {
- offlineRegionsNames.add(OfflineUtils.convertRegionName(offlineRegion.getMetadata()));
- }
-
- // Create args
- Bundle args = new Bundle();
- args.putStringArrayList(OfflineListRegionsDialog.ITEMS, offlineRegionsNames);
-
- // Show dialog
- OfflineListRegionsDialog offlineListRegionsDialog = new OfflineListRegionsDialog();
- offlineListRegionsDialog.setArguments(args);
- offlineListRegionsDialog.show(getSupportFragmentManager(), "list");
- }
-
- @Override
- public void onError(String error) {
- Log.e(LOG_TAG, "Error: " + error);
- }
- });
- }
-
- /*
- * Dialogs
- */
-
- @Override
- public void onDownloadRegionDialogPositiveClick(final String regionName) {
- if (TextUtils.isEmpty(regionName)) {
- Toast.makeText(OfflineActivity.this, "Region name cannot be empty.", Toast.LENGTH_SHORT).show();
- return;
+ // Start progress bar
+ Timber.d("Download started: " + regionName);
+ startProgress();
+
+ // Definition
+ LatLngBounds bounds = mapboxMap.getProjection().getVisibleRegion().latLngBounds;
+ double minZoom = mapboxMap.getCameraPosition().zoom;
+ double maxZoom = mapboxMap.getMaxZoomLevel();
+ float pixelRatio = this.getResources().getDisplayMetrics().density;
+ OfflineTilePyramidRegionDefinition definition = new OfflineTilePyramidRegionDefinition(
+ STYLE_URL, bounds, minZoom, maxZoom, pixelRatio);
+
+ // Sample way of encoding metadata from a JSONObject
+ byte[] metadata = OfflineUtils.convertRegionName(regionName);
+
+ // Create region
+ offlineManager.createOfflineRegion(definition, metadata, new OfflineManager.CreateOfflineRegionCallback() {
+ @Override
+ public void onCreate(OfflineRegion offlineRegion) {
+ Timber.d("Offline region created: " + regionName);
+ OfflineActivity.this.offlineRegion = offlineRegion;
+ launchDownload();
+ }
+
+ @Override
+ public void onError(String error) {
+ Timber.e("Error: " + error);
+ }
+ });
+ }
+
+ private void launchDownload() {
+ // Set an observer
+ offlineRegion.setObserver(new OfflineRegion.OfflineRegionObserver() {
+ @Override
+ public void onStatusChanged(OfflineRegionStatus status) {
+ // Compute a percentage
+ double percentage = status.getRequiredResourceCount() >= 0
+ ? (100.0 * status.getCompletedResourceCount() / status.getRequiredResourceCount()) :
+ 0.0;
+
+ if (status.isComplete()) {
+ // Download complete
+ endProgress("Region downloaded successfully.");
+ return;
+ } else if (status.isRequiredResourceCountPrecise()) {
+ // Switch to determinate state
+ setPercentage((int) Math.round(percentage));
}
- // Start progress bar
- Log.d(LOG_TAG, "Download started: " + regionName);
- startProgress();
-
- // Definition
- String styleUrl = mapboxMap.getStyleUrl();
- LatLngBounds bounds = mapboxMap.getProjection().getVisibleRegion().latLngBounds;
- double minZoom = mapboxMap.getCameraPosition().zoom;
- double maxZoom = mapboxMap.getMaxZoom();
- float pixelRatio = this.getResources().getDisplayMetrics().density;
- OfflineTilePyramidRegionDefinition definition = new OfflineTilePyramidRegionDefinition(
- styleUrl, bounds, minZoom, maxZoom, pixelRatio);
-
- // Sample way of encoding metadata from a JSONObject
- byte[] metadata = OfflineUtils.convertRegionName(regionName);
-
- // Create region
- offlineManager.createOfflineRegion(definition, metadata, new OfflineManager.CreateOfflineRegionCallback() {
- @Override
- public void onCreate(OfflineRegion offlineRegion) {
- Log.d(LOG_TAG, "Offline region created: " + regionName);
- OfflineActivity.this.offlineRegion = offlineRegion;
- launchDownload();
- }
-
- @Override
- public void onError(String error) {
- Log.e(LOG_TAG, "Error: " + error);
- }
- });
- }
-
- private void launchDownload() {
- // Set an observer
- offlineRegion.setObserver(new OfflineRegion.OfflineRegionObserver() {
- @Override
- public void onStatusChanged(OfflineRegionStatus status) {
- // Compute a percentage
- double percentage = status.getRequiredResourceCount() >= 0
- ? (100.0 * status.getCompletedResourceCount() / status.getRequiredResourceCount()) :
- 0.0;
-
- if (status.isComplete()) {
- // Download complete
- endProgress("Region downloaded successfully.");
- return;
- } else if (status.isRequiredResourceCountPrecise()) {
- // Switch to determinate state
- setPercentage((int) Math.round(percentage));
- }
-
- // Debug
- Log.d(LOG_TAG, String.format("%s/%s resources; %s bytes downloaded.",
- String.valueOf(status.getCompletedResourceCount()),
- String.valueOf(status.getRequiredResourceCount()),
- String.valueOf(status.getCompletedResourceSize())));
- }
-
- @Override
- public void onError(OfflineRegionError error) {
- Log.e(LOG_TAG, "onError reason: " + error.getReason());
- Log.e(LOG_TAG, "onError message: " + error.getMessage());
- }
-
- @Override
- public void mapboxTileCountLimitExceeded(long limit) {
- Log.e(LOG_TAG, "Mapbox tile count limit exceeded: " + limit);
- }
- });
-
- // Change the region state
- offlineRegion.setDownloadState(OfflineRegion.STATE_ACTIVE);
- }
-
- /*
- * Progress bar
- */
-
- private void startProgress() {
- // Disable buttons
- downloadRegion.setEnabled(false);
- listRegions.setEnabled(false);
-
- // Start and show the progress bar
- isEndNotified = false;
- progressBar.setIndeterminate(true);
- progressBar.setVisibility(View.VISIBLE);
- }
-
- private void setPercentage(final int percentage) {
- progressBar.setIndeterminate(false);
- progressBar.setProgress(percentage);
+ // Debug
+ Timber.d(String.format("%s/%s resources; %s bytes downloaded.",
+ String.valueOf(status.getCompletedResourceCount()),
+ String.valueOf(status.getRequiredResourceCount()),
+ String.valueOf(status.getCompletedResourceSize())));
+ }
+
+ @Override
+ public void onError(OfflineRegionError error) {
+ Timber.e("onError reason: " + error.getReason());
+ Timber.e("onError message: " + error.getMessage());
+ }
+
+ @Override
+ public void mapboxTileCountLimitExceeded(long limit) {
+ Timber.e("Mapbox tile count limit exceeded: " + limit);
+ }
+ });
+
+ // Change the region state
+ offlineRegion.setDownloadState(OfflineRegion.STATE_ACTIVE);
+ }
+
+ /*
+ * Progress bar
+ */
+ private void startProgress() {
+ // Disable buttons
+ downloadRegion.setEnabled(false);
+ listRegions.setEnabled(false);
+
+ // Start and show the progress bar
+ isEndNotified = false;
+ progressBar.setIndeterminate(true);
+ progressBar.setVisibility(View.VISIBLE);
+ }
+
+ private void setPercentage(final int percentage) {
+ progressBar.setIndeterminate(false);
+ progressBar.setProgress(percentage);
+ }
+
+ private void endProgress(final String message) {
+ // Don't notify more than once
+ if (isEndNotified) {
+ return;
}
- private void endProgress(final String message) {
- // Don't notify more than once
- if (isEndNotified) {
- return;
- }
+ // Enable buttons
+ downloadRegion.setEnabled(true);
+ listRegions.setEnabled(true);
- // Enable buttons
- downloadRegion.setEnabled(true);
- listRegions.setEnabled(true);
-
- // Stop and hide the progress bar
- isEndNotified = true;
- progressBar.setIndeterminate(false);
- progressBar.setVisibility(View.GONE);
-
- // Show a toast
- Toast.makeText(OfflineActivity.this, message, Toast.LENGTH_LONG).show();
- }
+ // Stop and hide the progress bar
+ isEndNotified = true;
+ progressBar.setIndeterminate(false);
+ progressBar.setVisibility(View.GONE);
+ // Show a toast
+ Toast.makeText(OfflineActivity.this, message, Toast.LENGTH_LONG).show();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.java
index 0530f1c157..a83cabba12 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.java
@@ -33,154 +33,158 @@ import java.util.List;
*/
public class UpdateMetadataActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
- private OfflineRegionMetadataAdapter adapter;
+ private OfflineRegionMetadataAdapter adapter;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_metadata_update);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_metadata_update);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
- ListView listView = (ListView) findViewById(R.id.listView);
- listView.setAdapter(adapter = new OfflineRegionMetadataAdapter(this));
- listView.setEmptyView(findViewById(android.R.id.empty));
- listView.setOnItemClickListener(this);
+ ListView listView = (ListView) findViewById(R.id.listView);
+ listView.setAdapter(adapter = new OfflineRegionMetadataAdapter(this));
+ listView.setEmptyView(findViewById(android.R.id.empty));
+ listView.setOnItemClickListener(this);
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ final OfflineRegion region = adapter.getItem(position);
+ String metadata = OfflineUtils.convertRegionName(region.getMetadata());
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("Rename metadata");
+
+ final EditText input = new EditText(this);
+ input.setText(metadata);
+ input.setInputType(InputType.TYPE_CLASS_TEXT);
+ input.setSelection(metadata.length());
+ builder.setView(input);
+
+ builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ updateMetadata(region, OfflineUtils.convertRegionName(input.getText().toString()));
+ }
+ });
+ builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.cancel();
+ }
+ });
+
+ builder.show();
+ }
+
+ private void updateMetadata(OfflineRegion region, byte[] metadata) {
+ region.updateMetadata(metadata, new OfflineRegion.OfflineRegionUpdateMetadataCallback() {
+ @Override
+ public void onUpdate(byte[] metadata) {
+ adapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onError(String error) {
+ Toast.makeText(
+ UpdateMetadataActivity.this,
+ "Region metadata update failed with " + error,
+ Toast.LENGTH_LONG
+ ).show();
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ loadOfflineRegions();
+ }
+
+ private void loadOfflineRegions() {
+ OfflineManager.getInstance(this).listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {
+ @Override
+ public void onList(OfflineRegion[] offlineRegions) {
+ if (offlineRegions != null && offlineRegions.length > 0) {
+ adapter.setOfflineRegions(Arrays.asList(offlineRegions));
+ }
+ }
+
+ @Override
+ public void onError(String error) {
+ Toast.makeText(UpdateMetadataActivity.this, "Error loading regions " + error, Toast.LENGTH_LONG).show();
+ }
+ });
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- final OfflineRegion region = adapter.getItem(position);
- String metadata = OfflineUtils.convertRegionName(region.getMetadata());
-
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle("Rename metadata");
-
- final EditText input = new EditText(this);
- input.setText(metadata);
- input.setInputType(InputType.TYPE_CLASS_TEXT);
- input.setSelection(metadata.length());
- builder.setView(input);
-
- builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- updateMetadata(region, OfflineUtils.convertRegionName(input.getText().toString()));
- }
- });
- builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.cancel();
- }
- });
-
- builder.show();
+ private static class OfflineRegionMetadataAdapter extends BaseAdapter {
+
+ private Context context;
+ private List<OfflineRegion> offlineRegions;
+
+ OfflineRegionMetadataAdapter(Context ctx) {
+ context = ctx;
+ offlineRegions = new ArrayList<>();
}
- private void updateMetadata(OfflineRegion region, byte[] metadata) {
- region.updateMetadata(metadata, new OfflineRegion.OfflineRegionUpdateMetadataCallback() {
- @Override
- public void onUpdate(byte[] metadata) {
- adapter.notifyDataSetChanged();
- }
-
- @Override
- public void onError(String error) {
- Toast.makeText(UpdateMetadataActivity.this, "Region metadata update failed with " + error, Toast.LENGTH_LONG).show();
- }
- });
+ void setOfflineRegions(List<OfflineRegion> offlineRegions) {
+ this.offlineRegions = offlineRegions;
+ notifyDataSetChanged();
}
@Override
- protected void onStart() {
- super.onStart();
- loadOfflineRegions();
+ public int getCount() {
+ return offlineRegions.size();
}
- private void loadOfflineRegions() {
- OfflineManager.getInstance(this).listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {
- @Override
- public void onList(OfflineRegion[] offlineRegions) {
- if (offlineRegions != null && offlineRegions.length > 0) {
- adapter.setOfflineRegions(Arrays.asList(offlineRegions));
- }
- }
-
- @Override
- public void onError(String error) {
- Toast.makeText(UpdateMetadataActivity.this, "Error loading regions " + error, Toast.LENGTH_LONG).show();
- }
- });
+ @Override
+ public OfflineRegion getItem(int position) {
+ return offlineRegions.get(position);
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ public long getItemId(int position) {
+ return position;
}
- private static class OfflineRegionMetadataAdapter extends BaseAdapter {
-
- private Context context;
- private List<OfflineRegion> offlineRegions;
-
- OfflineRegionMetadataAdapter(Context ctx) {
- context = ctx;
- offlineRegions = new ArrayList<>();
- }
-
- void setOfflineRegions(List<OfflineRegion> offlineRegions) {
- this.offlineRegions = offlineRegions;
- notifyDataSetChanged();
- }
-
- @Override
- public int getCount() {
- return offlineRegions.size();
- }
-
- @Override
- public OfflineRegion getItem(int position) {
- return offlineRegions.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- ViewHolder holder;
-
- if (convertView == null) {
- holder = new ViewHolder();
- convertView = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false);
- holder.text = (TextView) convertView.findViewById(android.R.id.text1);
- convertView.setTag(holder);
- } else {
- holder = (ViewHolder) convertView.getTag();
- }
-
- holder.text.setText(OfflineUtils.convertRegionName(getItem(position).getMetadata()));
- return convertView;
- }
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ViewHolder holder;
+
+ if (convertView == null) {
+ holder = new ViewHolder();
+ convertView = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false);
+ holder.text = (TextView) convertView.findViewById(android.R.id.text1);
+ convertView.setTag(holder);
+ } else {
+ holder = (ViewHolder) convertView.getTag();
+ }
+
+ holder.text.setText(OfflineUtils.convertRegionName(getItem(position).getMetadata()));
+ return convertView;
+ }
- static class ViewHolder {
- TextView text;
- }
+ static class ViewHolder {
+ TextView text;
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java
index 44380ae5b5..0b102057b7 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java
@@ -1,143 +1,170 @@
package com.mapbox.mapboxsdk.testapp.activity.style;
+import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
-import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.MenuItem;
import android.view.View;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
-import com.mapbox.mapboxsdk.style.layers.Layer;
+import com.mapbox.mapboxsdk.style.layers.LineLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.testapp.R;
import java.net.MalformedURLException;
import java.net.URL;
+import static com.mapbox.mapboxsdk.style.layers.Filter.in;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius;
-/**
- * Example to add a circle as a layer using runtime style API, contains adding
- * GeoJSON as source that contains 1 Feature with a Point geometry, adding a circle layer and
- * changing circle layer properties as size and colors.
- */
public class CircleLayerActivity extends AppCompatActivity {
- private MapboxMap mapboxMap;
- private MapView mapView;
- private Layer circleLayer;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_circlelayer);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ private static final String[] STOPS_FOR_ROUTE = new String[] {"99009", "99131", "99049", "99039", "99029", "99019",
+ "98079", "98069", "97099", "97089", "97079", "97069", "97209", "97059", "97049", "97039", "97019", "96069",
+ "96059", "96049", "96099", "96089", "96079", "85079", "85089", "85069", "85059", "85099", "84069", "84059",
+ "84049", "84039", "84029", "84019", "83099", "83079", "83059", "83049", "83029", "82069", "82049", "82029",
+ "82109", "81069", "81049", "81029", "80089", "80069", "80049", "80039", "80029", "01319", "01219", "01129",
+ "01059", "01119", "01019", "04159", "04149", "04229", "04239", "05059", "05049", "05039", "05019", "10589"};
+
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private CircleLayer layer;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_circle_layer);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull final MapboxMap map) {
+ mapboxMap = map;
+ try {
+ mapboxMap.addSource(new GeoJsonSource("bus_stop",
+ new URL("https://raw.githubusercontent.com/cheeaun/busrouter-sg/master/data/2/bus-stops.geojson")));
+ } catch (MalformedURLException malformedUrlException) {
+ Timber.e("That's not an url... ", malformedUrlException);
}
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap map) {
- mapboxMap = map;
- FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
- fab.setColorFilter(ContextCompat.getColor(CircleLayerActivity.this, R.color.primary));
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (circleLayer == null) {
- // first time
- try {
- mapboxMap.addSource(new GeoJsonSource("point", new URL("https://gist.githubusercontent.com/anonymous/87eca90e80a72b1b42be9d0201ec3c8e/raw/acbb46384fd56044a504f122950d0637d98b4e7a/map.geojson")));
- } catch (MalformedURLException malformedUrlException) {
- Log.e(
- MapboxConstants.TAG,
- "That's not an url... " + malformedUrlException.getMessage()
- );
- }
-
- circleLayer = new CircleLayer("circleLayer", "point");
- circleLayer.setProperties(
- circleColor(ResourcesCompat.getColor(getResources(), R.color.primary_dark, getTheme())),
- circleRadius(getResources().getDimension(R.dimen.circle_size))
- );
-
- // lets add a circle below labels!
- mapboxMap.addLayer(circleLayer, "waterway-label");
- } else {
- // change size and color
- circleLayer = mapboxMap.getLayer("circleLayer");
- circleLayer.setProperties(
- circleRadius(mapView.getTag() == null
- ? getResources().getDimension(R.dimen.activity_horizontal_margin)
- : getResources().getDimension(R.dimen.circle_size)),
- circleColor(mapView.getTag() == null ? ResourcesCompat.getColor(
- getResources(), R.color.blue_accent, getTheme()) : ResourcesCompat.getColor(
- getResources(), R.color.green_accent, getTheme())));
- mapView.setTag(mapView.getTag() == null ? mapboxMap : null);
- }
- }
- });
+ layer = new CircleLayer("stops_layer", "bus_stop");
+ layer.setProperties(
+ circleColor(Color.parseColor("#FF9800")),
+ circleRadius(1.0f)
+ );
+
+ mapboxMap.addLayer(layer);
+
+ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setColorFilter(ContextCompat.getColor(CircleLayerActivity.this, R.color.primary));
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ // filter out stops for our route
+ layer.setFilter(in("number", STOPS_FOR_ROUTE));
+
+ // add route as a line
+ try {
+ mapboxMap.addSource(new GeoJsonSource("bus_route",
+ new URL("https://gist.githubusercontent.com/tobrun/7fbc0fe7e9ffea509f7608cda2601d5d/raw/"
+ + "a4b8cc289020f91fa2e1553524820054395e36f5/line.geojson")));
+ } catch (MalformedURLException malformedUrlException) {
+ Timber.e("That's not an url... ", malformedUrlException);
}
+ LineLayer lineLayer = new LineLayer("route_layer", "bus_route");
+ mapboxMap.addLayer(lineLayer, "stops_layer");
+
+ // move camera to start route
+ mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .target(new LatLng(1.3896777, 103.9874997))
+ .bearing(225)
+ .tilt(45)
+ .zoom(13)
+ .build()
+ ), 1750);
+ }
});
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-} \ No newline at end of file
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CustomSpriteActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CustomSpriteActivity.java
index 69108c6e1b..d68872a5ba 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CustomSpriteActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CustomSpriteActivity.java
@@ -1,156 +1,166 @@
package com.mapbox.mapboxsdk.testapp.activity.style;
-import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
-import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.MenuItem;
import android.view.View;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
-import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.services.commons.geojson.Feature;
import com.mapbox.services.commons.geojson.FeatureCollection;
import com.mapbox.services.commons.geojson.Point;
import com.mapbox.services.commons.models.Position;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
/**
* Example to add a sprite image and use it in a Symbol Layer
*/
public class CustomSpriteActivity extends AppCompatActivity {
- private static final String TAG = CustomSpriteActivity.class.getSimpleName();
- private static final String CUSTOM_ICON = "custom-icon";
-
- private MapboxMap mapboxMap;
- private MapView mapView;
- private Layer layer;
-
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_add_sprite);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap map) {
- mapboxMap = map;
- final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
- fab.setColorFilter(ContextCompat.getColor(CustomSpriteActivity.this, R.color.primary));
- fab.setOnClickListener(new View.OnClickListener() {
- private Point point;
-
- @Override
- public void onClick(View view) {
- if (point == null) {
- Log.i(TAG, "First click -> Car");
- // Add an icon to reference later
- mapboxMap.addImage(CUSTOM_ICON, BitmapFactory.decodeResource(getResources(), R.drawable.ic_car_top));
-
- //Add a source with a geojson point
- point = Point.fromCoordinates(Position.fromCoordinates(13.400972d, 52.519003d));
- mapboxMap.addSource(new GeoJsonSource("point", FeatureCollection.fromFeatures(new Feature[]{Feature.fromGeometry(point)})));
-
- //Add a symbol layer that references that point source
- layer = new SymbolLayer("layer", "point");
- layer.setProperties(
- //Set the id of the sprite to use
- iconImage(CUSTOM_ICON)
- );
-
- // lets add a circle below labels!
- mapboxMap.addLayer(layer, "waterway-label");
-
- fab.setImageResource(R.drawable.ic_directions_car_black_24dp);
- } else {
- //Update point
- point = Point.fromCoordinates(Position.fromCoordinates(point.getCoordinates().getLongitude() + 0.001, point.getCoordinates().getLatitude() + 0.001));
- GeoJsonSource source = mapboxMap.getSourceAs("point");
- source.setGeoJson(FeatureCollection.fromFeatures(new Feature[]{Feature.fromGeometry(point)}));
-
- //Move the camera as well
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(point.getCoordinates().getLatitude(), point.getCoordinates().getLongitude())));
- }
- }
- });
- }
- });
- }
+ private static final String CUSTOM_ICON = "custom-icon";
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
+ private MapboxMap mapboxMap;
+ private MapView mapView;
+ private Layer layer;
+ private GeoJsonSource source;
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_add_sprite);
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- @Override
- public void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull final MapboxMap map) {
+ mapboxMap = map;
+ final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setColorFilter(ContextCompat.getColor(CustomSpriteActivity.this, R.color.primary));
+ fab.setOnClickListener(new View.OnClickListener() {
+ private Point point;
+
+ @Override
+ public void onClick(View view) {
+ if (point == null) {
+ Timber.i("First click -> Car");
+ // Add an icon to reference later
+ mapboxMap.addImage(CUSTOM_ICON, BitmapFactory.decodeResource(getResources(), R.drawable.ic_car_top));
+
+ //Add a source with a geojson point
+ point = Point.fromCoordinates(Position.fromCoordinates(13.400972d, 52.519003d));
+ source = new GeoJsonSource(
+ "point",
+ FeatureCollection.fromFeatures(new Feature[] {Feature.fromGeometry(point)})
+ );
+ mapboxMap.addSource(source);
+
+ //Add a symbol layer that references that point source
+ layer = new SymbolLayer("layer", "point");
+ layer.setProperties(
+ //Set the id of the sprite to use
+ iconImage(CUSTOM_ICON)
+ );
+
+ // lets add a circle below labels!
+ mapboxMap.addLayer(layer, "waterway-label");
+
+ fab.setImageResource(R.drawable.ic_directions_car_black_24dp);
+ } else {
+ //Update point
+ point = Point.fromCoordinates(
+ Position.fromCoordinates(point.getCoordinates().getLongitude() + 0.001,
+ point.getCoordinates().getLatitude() + 0.001)
+ );
+ source.setGeoJson(FeatureCollection.fromFeatures(new Feature[] {Feature.fromGeometry(point)}));
+
+ //Move the camera as well
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(
+ point.getCoordinates().getLatitude(), point.getCoordinates().getLongitude())));
+ }
+ }
+ });
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java
index 9d13ee165d..33fc7f60a6 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java
@@ -6,7 +6,9 @@ import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.MenuItem;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
@@ -37,140 +39,151 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textSize;
* Sample Activity to show off geojson source clustering and filter usage
*/
public class GeoJsonClusteringActivity extends AppCompatActivity {
- private static final String TAG = GeoJsonClusteringActivity.class.getSimpleName();
-
- private MapView mapView;
- private MapboxMap mapboxMap;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_geojson_clustering);
- setupActionBar();
-
- //Initialize map as normal
- mapView = (MapView) findViewById(R.id.mapView);
- //noinspection ConstantConditions
- mapView.onCreate(savedInstanceState);
-
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.7749, 122.4194), 0));
-
- //Add a clustered source with some layers
- addClusteredGeoJsonSource();
- }
- });
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_geojson_clustering);
+
+ setupActionBar();
+
+ //Initialize map as normal
+ mapView = (MapView) findViewById(R.id.mapView);
+ //noinspection ConstantConditions
+ mapView.onCreate(savedInstanceState);
+
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.7749, 122.4194), 0));
+
+ //Add a clustered source with some layers
+ addClusteredGeoJsonSource();
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
+ }
+
+ private void addClusteredGeoJsonSource() {
+ //Add a clustered source
+ try {
+ mapboxMap.addSource(
+ new GeoJsonSource("earthquakes",
+ new URL("https://www.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson"),
+ new GeoJsonOptions()
+ .withCluster(true)
+ .withClusterMaxZoom(14)
+ .withClusterRadius(50)
+ )
+ );
+ } catch (MalformedURLException malformedUrlException) {
+ Timber.e("That's not an url... " + malformedUrlException.getMessage());
}
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ //Add unclustered layer
+ int[][] layers = new int[][] {
+ new int[] {150, ResourcesCompat.getColor(getResources(), R.color.red_accent, getTheme())},
+ new int[] {20, ResourcesCompat.getColor(getResources(), R.color.green_accent, getTheme())},
+ new int[] {0, ResourcesCompat.getColor(getResources(), R.color.blue_accent, getTheme())}
+ };
+
+ SymbolLayer unclustered = new SymbolLayer("unclustered-points", "earthquakes");
+ unclustered.setProperties(iconImage("marker-15"));
+ mapboxMap.addLayer(unclustered);
+
+ for (int i = 0; i < layers.length; i++) {
+ //Add some nice circles
+ CircleLayer circles = new CircleLayer("cluster-" + i, "earthquakes");
+ circles.setProperties(
+ circleColor(layers[i][1]),
+ circleRadius(18f)
+ );
+ circles.setFilter(
+ i == 0
+ ? gte("point_count", layers[i][0]) :
+ all(gte("point_count", layers[i][0]), lt("point_count", layers[i - 1][0]))
+ );
+ mapboxMap.addLayer(circles);
}
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ //Add the count labels
+ SymbolLayer count = new SymbolLayer("count", "earthquakes");
+ count.setProperties(
+ textField("{point_count}"),
+ textSize(12f),
+ textColor(Color.WHITE)
+ );
+ mapboxMap.addLayer(count);
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- private void addClusteredGeoJsonSource() {
- //Add a clustered source
- try {
- mapboxMap.addSource(
- new GeoJsonSource("earthquakes",
- new URL("https://www.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson"),
- new GeoJsonOptions()
- .withCluster(true)
- .withClusterMaxZoom(14)
- .withClusterRadius(50)
- )
- );
- } catch (MalformedURLException malformedUrlException) {
- Log.e(TAG, "That's not an url... " + malformedUrlException.getMessage());
- }
-
- //Add unclustered layer
- int[][] layers = new int[][]{
- new int[]{150, ResourcesCompat.getColor(getResources(), R.color.red_accent, getTheme())},
- new int[]{20, ResourcesCompat.getColor(getResources(), R.color.green_accent, getTheme())},
- new int[]{0, ResourcesCompat.getColor(getResources(), R.color.blue_accent, getTheme())}
- };
-
- SymbolLayer unclustered = new SymbolLayer("unclustered-points", "earthquakes");
- unclustered.setProperties(iconImage("marker-15"));
- mapboxMap.addLayer(unclustered);
-
- for (int i = 0; i < layers.length; i++) {
- //Add some nice circles
- CircleLayer circles = new CircleLayer("cluster-" + i, "earthquakes");
- circles.setProperties(
- circleColor(layers[i][1]),
- circleRadius(18f)
- );
- circles.setFilter(
- i == 0
- ? gte("point_count", layers[i][0]) :
- all(gte("point_count", layers[i][0]), lt("point_count", layers[i - 1][0]))
- );
- mapboxMap.addLayer(circles);
- }
-
- //Add the count labels
- SymbolLayer count = new SymbolLayer("count", "earthquakes");
- count.setProperties(
- textField("{point_count}"),
- textSize(12f),
- textColor(Color.WHITE)
- );
- mapboxMap.addLayer(count);
-
-
- //Zoom out to start
- mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(1));
- }
+ //Zoom out to start
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(1));
+ }
- private void setupActionBar() {
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ private void setupActionBar() {
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java
index debd44fb1f..fad4f9714d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java
@@ -6,10 +6,11 @@ import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.view.MenuItem;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
@@ -30,112 +31,119 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
*/
public class RealTimeGeoJsonActivity extends AppCompatActivity implements OnMapReadyCallback {
- private final static String ID_GEOJSON_LAYER = "wanderdrone";
- private final static String ID_GEOJSON_SOURCE = ID_GEOJSON_LAYER;
- private final static String URL_GEOJSON_SOURCE = "https://wanderdrone.appspot.com/";
+ private static final String ID_GEOJSON_LAYER = "wanderdrone";
+ private static final String ID_GEOJSON_SOURCE = ID_GEOJSON_LAYER;
+ private static final String URL_GEOJSON_SOURCE = "https://wanderdrone.appspot.com/";
- private MapView mapView;
- private MapboxMap mapboxMap;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
- private Handler handler;
- private Runnable runnable;
+ private Handler handler;
+ private Runnable runnable;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_default);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
- }
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_default);
- @Override
- public void onMapReady(@NonNull final MapboxMap map) {
- mapboxMap = map;
-
- // add source
- try {
- mapboxMap.addSource(new GeoJsonSource(ID_GEOJSON_SOURCE, new URL(URL_GEOJSON_SOURCE)));
- }catch (MalformedURLException e){
- Log.e(MapboxConstants.TAG, "Invalid URL", e);
- }
-
- // add layer
- SymbolLayer layer = new SymbolLayer(ID_GEOJSON_LAYER, ID_GEOJSON_SOURCE);
- layer.setProperties(iconImage("rocket-15"));
- mapboxMap.addLayer(layer);
-
- // loop refresh geojson
- handler = new Handler();
- runnable = new RefreshGeoJsonRunnable(mapboxMap, handler);
- handler.postDelayed(runnable, 2000);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @Override
- protected void onStop() {
- super.onStop();
- handler.removeCallbacks(runnable);
- }
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ @Override
+ public void onMapReady(@NonNull final MapboxMap map) {
+ mapboxMap = map;
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ // add source
+ try {
+ mapboxMap.addSource(new GeoJsonSource(ID_GEOJSON_SOURCE, new URL(URL_GEOJSON_SOURCE)));
+ } catch (MalformedURLException malformedUrlException) {
+ Timber.e("Invalid URL", malformedUrlException);
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ // add layer
+ SymbolLayer layer = new SymbolLayer(ID_GEOJSON_LAYER, ID_GEOJSON_SOURCE);
+ layer.setProperties(iconImage("rocket-15"));
+ mapboxMap.addLayer(layer);
+
+ // loop refresh geojson
+ handler = new Handler();
+ runnable = new RefreshGeoJsonRunnable(mapboxMap, handler);
+ handler.postDelayed(runnable, 2000);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ handler.removeCallbacks(runnable);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
- private static class RefreshGeoJsonRunnable implements Runnable {
+ private static class RefreshGeoJsonRunnable implements Runnable {
- private MapboxMap mapboxMap;
- private Handler handler;
+ private MapboxMap mapboxMap;
+ private Handler handler;
- RefreshGeoJsonRunnable(MapboxMap mapboxMap, Handler handler) {
- this.mapboxMap = mapboxMap;
- this.handler = handler;
- }
+ RefreshGeoJsonRunnable(MapboxMap mapboxMap, Handler handler) {
+ this.mapboxMap = mapboxMap;
+ this.handler = handler;
+ }
- @Override
- public void run() {
- ((GeoJsonSource) mapboxMap.getSource(ID_GEOJSON_SOURCE)).setUrl(URL_GEOJSON_SOURCE);
- handler.postDelayed(this, 2000);
- }
+ @Override
+ public void run() {
+ ((GeoJsonSource) mapboxMap.getSource(ID_GEOJSON_SOURCE)).setUrl(URL_GEOJSON_SOURCE);
+ handler.postDelayed(this, 2000);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java
index efe82ee9a6..2ac3a6fb00 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java
@@ -7,7 +7,6 @@ import android.support.annotation.RawRes;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
@@ -44,7 +43,8 @@ import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
-import static android.os.Looper.getMainLooper;
+import timber.log.Timber;
+
import static com.mapbox.mapboxsdk.style.layers.Filter.all;
import static com.mapbox.mapboxsdk.style.layers.Filter.eq;
import static com.mapbox.mapboxsdk.style.layers.Filter.gte;
@@ -74,498 +74,513 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
* Sample Activity to show off the runtime style api
*/
public class RuntimeStyleActivity extends AppCompatActivity {
- private static final String TAG = RuntimeStyleActivity.class.getSimpleName();
-
- private MapView mapView;
- private MapboxMap mapboxMap;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_runtime_style);
-
- setupActionBar();
-
- //Initialize map as normal
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
-
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- //Store for later
- mapboxMap = map;
-
- //Center and Zoom (Amsterdam, zoomed to streets)
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.379189, 4.899431), 14));
- }
- });
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_runtime_style, menu);
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_runtime_style);
+
+ setupActionBar();
+
+ //Initialize map as normal
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+
+
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap map) {
+ //Store for later
+ mapboxMap = map;
+
+ //Center and Zoom (Amsterdam, zoomed to streets)
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.379189, 4.899431), 14));
+ }
+ });
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_runtime_style, menu);
+ return true;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
return true;
+ case R.id.action_water_color:
+ setWaterColor();
+ return true;
+ case R.id.action_background_opacity:
+ setBackgroundOpacity();
+ return true;
+ case R.id.action_road_avoid_edges:
+ setRoadSymbolPlacement();
+ return true;
+ case R.id.action_layer_visibility:
+ setLayerInvisible();
+ return true;
+ case R.id.action_remove_layer:
+ removeBuildings();
+ return true;
+ case R.id.action_add_parks_layer:
+ addParksLayer();
+ return true;
+ case R.id.action_add_dynamic_parks_layer:
+ addDynamicParksLayer();
+ return true;
+ case R.id.action_add_terrain_layer:
+ addTerrainLayer();
+ return true;
+ case R.id.action_add_satellite_layer:
+ addSatelliteLayer();
+ return true;
+ case R.id.action_update_water_color_on_zoom:
+ updateWaterColorOnZoom();
+ return true;
+ case R.id.action_add_custom_tiles:
+ addCustomTileSource();
+ return true;
+ case R.id.action_fill_filter:
+ styleFillFilterLayer();
+ return true;
+ case R.id.action_line_filter:
+ styleLineFilterLayer();
+ return true;
+ case R.id.action_numeric_filter:
+ styleNumericFillLayer();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ }
+
+ private void setLayerInvisible() {
+ String[] roadLayers = new String[] {"water"};
+ for (String roadLayer : roadLayers) {
+ Layer layer = mapboxMap.getLayer(roadLayer);
+ if (layer != null) {
+ layer.setProperties(visibility(NONE));
+ }
}
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ }
+
+ private void setRoadSymbolPlacement() {
+ //Zoom so that the labels are visible first
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(14), new DefaultCallback() {
+ @Override
+ public void onFinish() {
+ String[] roadLayers = new String[] {"road-label-small", "road-label-medium", "road-label-large"};
+ for (String roadLayer : roadLayers) {
+ Layer layer = mapboxMap.getLayer(roadLayer);
+ if (layer != null) {
+ layer.setProperties(symbolPlacement(SYMBOL_PLACEMENT_POINT));
+ }
+ }
+ }
+ });
+ }
+
+ private void setBackgroundOpacity() {
+ Layer background = mapboxMap.getLayer("background");
+ if (background != null) {
+ background.setProperties(backgroundOpacity(0.2f));
}
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ }
+
+ private void setWaterColor() {
+ Layer water = mapboxMap.getLayer("water");
+ if (water != null) {
+ water.setProperties(
+ visibility(VISIBLE),
+ fillColor(Color.RED)
+ );
+ } else {
+ Toast.makeText(RuntimeStyleActivity.this, "No water layer in this style", Toast.LENGTH_SHORT).show();
}
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ }
+
+ private void removeBuildings() {
+ //Zoom to see buildings first
+ try {
+ mapboxMap.removeLayer("building");
+ } catch (NoSuchLayerException noSuchLayerException) {
+ Toast.makeText(RuntimeStyleActivity.this, noSuchLayerException.getMessage(), Toast.LENGTH_SHORT).show();
}
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- case R.id.action_water_color:
- setWaterColor();
- return true;
- case R.id.action_background_opacity:
- setBackgroundOpacity();
- return true;
- case R.id.action_road_avoid_edges:
- setRoadSymbolPlacement();
- return true;
- case R.id.action_layer_visibility:
- setLayerInvisible();
- return true;
- case R.id.action_remove_layer:
- removeBuildings();
- return true;
- case R.id.action_add_parks_layer:
- addParksLayer();
- return true;
- case R.id.action_add_dynamic_parks_layer:
- addDynamicParksLayer();
- return true;
- case R.id.action_add_terrain_layer:
- addTerrainLayer();
- return true;
- case R.id.action_add_satellite_layer:
- addSatelliteLayer();
- return true;
- case R.id.action_update_water_color_on_zoom:
- updateWaterColorOnZoom();
- return true;
- case R.id.action_add_custom_tiles:
- addCustomTileSource();
- return true;
- case R.id.action_fill_filter:
- styleFillFilterLayer();
- return true;
- case R.id.action_line_filter:
- styleLineFilterLayer();
- return true;
- case R.id.action_numeric_filter:
- styleNumericFillLayer();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ }
+
+ private void addParksLayer() {
+ //Add a source
+ Source source;
+ try {
+ source = new GeoJsonSource("amsterdam-spots", readRawResource(R.raw.amsterdam));
+ } catch (IOException ioException) {
+ Toast.makeText(
+ RuntimeStyleActivity.this,
+ "Couldn't add source: " + ioException.getMessage(),
+ Toast.LENGTH_SHORT).show();
+ return;
}
- private void setLayerInvisible() {
- String[] roadLayers = new String[]{"water"};
- for (String roadLayer : roadLayers) {
- Layer layer = mapboxMap.getLayer(roadLayer);
- if (layer != null) {
- layer.setProperties(visibility(NONE));
- }
- }
+ mapboxMap.addSource(source);
+
+ FillLayer layer = new FillLayer("parksLayer", "amsterdam-spots");
+ layer.setProperties(
+ fillColor(Color.RED),
+ fillOutlineColor(Color.BLUE),
+ fillOpacity(0.3f),
+ fillAntialias(true)
+ );
+
+ //Only show me parks (except westerpark with stroke-width == 3)
+ layer.setFilter(all(eq("type", "park"), eq("stroke-width", 2)));
+
+ mapboxMap.addLayer(layer, "building");
+ //layer.setPaintProperty(fillColor(Color.RED)); //XXX But not after the object is attached
+
+ //Or get the object later and set it. It's all good.
+ mapboxMap.getLayer("parksLayer").setProperties(fillColor(Color.RED));
+
+ //You can get a typed layer, if you're sure it's of that type. Use with care
+ layer = mapboxMap.getLayerAs("parksLayer");
+ //And get some properties
+ PropertyValue<Boolean> fillAntialias = layer.getFillAntialias();
+ Timber.d("Fill anti alias: " + fillAntialias.getValue());
+ layer.setProperties(fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP));
+ PropertyValue<String> fillTranslateAnchor = layer.getFillTranslateAnchor();
+ Timber.d("Fill translate anchor: " + fillTranslateAnchor.getValue());
+ PropertyValue<String> visibility = layer.getVisibility();
+ Timber.d("Visibility: " + visibility.getValue());
+
+ //Get a good look at it all
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(12));
+ }
+
+ private void addDynamicParksLayer() {
+ //Load some data
+ FeatureCollection parks;
+ try {
+ String json = readRawResource(R.raw.amsterdam);
+ parks = FeatureCollection.fromJson(json);
+ } catch (IOException ioException) {
+ Toast.makeText(
+ RuntimeStyleActivity.this,
+ "Couldn't add source: " + ioException.getMessage(),
+ Toast.LENGTH_SHORT
+ ).show();
+ return;
}
- private void setRoadSymbolPlacement() {
- //Zoom so that the labels are visible first
- mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(14), new DefaultCallback() {
- @Override
- public void onFinish() {
- String[] roadLayers = new String[]{"road-label-small", "road-label-medium", "road-label-large"};
- for (String roadLayer : roadLayers) {
- Layer layer = mapboxMap.getLayer(roadLayer);
- if (layer != null) {
- layer.setProperties(symbolPlacement(SYMBOL_PLACEMENT_POINT));
- }
- }
- }
- });
- }
+ //Add an empty source
+ mapboxMap.addSource(new GeoJsonSource("dynamic-park-source"));
- private void setBackgroundOpacity() {
- Layer background = mapboxMap.getLayer("background");
- if (background != null) {
- background.setProperties(backgroundOpacity(0.2f));
- }
- }
+ FillLayer layer = new FillLayer("dynamic-parks-layer", "dynamic-park-source");
+ layer.setProperties(
+ fillColor(Color.GREEN),
+ fillOutlineColor(Color.GREEN),
+ fillOpacity(0.8f),
+ fillAntialias(true)
+ );
- private void setWaterColor() {
- Layer water = mapboxMap.getLayer("water");
- if (water != null) {
- water.setProperties(
- visibility(VISIBLE),
- fillColor(Color.RED)
- );
- } else {
- Toast.makeText(RuntimeStyleActivity.this, "No water layer in this style", Toast.LENGTH_SHORT).show();
- }
- }
+ //Only show me parks
+ layer.setFilter(all(eq("type", "park")));
- private void removeBuildings() {
- //Zoom to see buildings first
- try {
- mapboxMap.removeLayer("building");
- } catch (NoSuchLayerException noSuchLayerException) {
- Toast.makeText(RuntimeStyleActivity.this, noSuchLayerException.getMessage(), Toast.LENGTH_SHORT).show();
- }
- }
+ mapboxMap.addLayer(layer);
- private void addParksLayer() {
- //Add a source
- Source source;
- try {
- source = new GeoJsonSource("amsterdam-spots", readRawResource(R.raw.amsterdam));
- } catch (IOException ioException) {
- Toast.makeText(
- RuntimeStyleActivity.this,
- "Couldn't add source: " + ioException.getMessage(),
- Toast.LENGTH_SHORT).show();
- return;
- }
+ //Get a good look at it all
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(12));
- mapboxMap.addSource(source);
-
- FillLayer layer = new FillLayer("parksLayer", "amsterdam-spots");
- layer.setProperties(
- fillColor(Color.RED),
- fillOutlineColor(Color.BLUE),
- fillOpacity(0.3f),
- fillAntialias(true)
- );
-
- //Only show me parks (except westerpark with stroke-width == 3)
- layer.setFilter(all(eq("type", "park"), eq("stroke-width", 2)));
-
- mapboxMap.addLayer(layer, "building");
- //layer.setPaintProperty(fillColor(Color.RED)); //XXX But not after the object is attached
-
- //Or get the object later and set it. It's all good.
- mapboxMap.getLayer("parksLayer").setProperties(fillColor(Color.RED));
-
- //You can get a typed layer, if you're sure it's of that type. Use with care
- layer = mapboxMap.getLayerAs("parksLayer");
- //And get some properties
- PropertyValue<Boolean> fillAntialias = layer.getFillAntialias();
- Log.d(TAG, "Fill anti alias: " + fillAntialias.getValue());
- layer.setProperties(fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP));
- PropertyValue<String> fillTranslateAnchor = layer.getFillTranslateAnchor();
- Log.d(TAG, "Fill translate anchor: " + fillTranslateAnchor.getValue());
- PropertyValue<String> visibility = layer.getVisibility();
- Log.d(TAG, "Visibility: " + visibility.getValue());
-
- //Get a good look at it all
- mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(12));
- }
+ //Animate the parks source
+ animateParksSource(parks, 0);
+ }
- private void addDynamicParksLayer() {
- //Load some data
- FeatureCollection parks;
- try {
- String json = readRawResource(R.raw.amsterdam);
- parks = FeatureCollection.fromJson(json);
- } catch (IOException e) {
- Toast.makeText(RuntimeStyleActivity.this, "Couldn't add source: " + e.getMessage(), Toast.LENGTH_SHORT).show();
- return;
+ private void animateParksSource(final FeatureCollection parks, final int counter) {
+ Handler handler = new Handler(getMainLooper());
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (mapboxMap == null) {
+ return;
}
- //Add an empty source
- mapboxMap.addSource(new GeoJsonSource("dynamic-park-source"));
+ Timber.d("Updating parks source");
+ //change the source
+ int park = counter < parks.getFeatures().size() - 1 ? counter : 0;
- FillLayer layer = new FillLayer("dynamic-parks-layer", "dynamic-park-source");
- layer.setProperties(
- fillColor(Color.GREEN),
- fillOutlineColor(Color.GREEN),
- fillOpacity(0.8f),
- fillAntialias(true)
- );
+ GeoJsonSource source = mapboxMap.getSourceAs("dynamic-park-source");
- //Only show me parks
- layer.setFilter(all(eq("type", "park")));
-
- mapboxMap.addLayer(layer);
-
- //Get a good look at it all
- mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(12));
+ if (source == null) {
+ Timber.e("Source not found");
+ Toast.makeText(RuntimeStyleActivity.this, "Source not found", Toast.LENGTH_SHORT).show();
+ return;
+ }
- //Animate the parks source
- animateParksSource(parks, 0);
+ List<Feature> features = new ArrayList<>();
+ features.add(parks.getFeatures().get(park));
+ source.setGeoJson(FeatureCollection.fromFeatures(features));
+
+ //Re-post
+ animateParksSource(parks, park + 1);
+ }
+ }, counter == 0 ? 100 : 1000);
+ }
+
+ private void addTerrainLayer() {
+ //Add a source
+ Source source = new VectorSource("my-terrain-source", "mapbox://mapbox.mapbox-terrain-v2");
+ mapboxMap.addSource(source);
+
+ LineLayer layer = new LineLayer("terrainLayer", "my-terrain-source");
+ layer.setSourceLayer("contour");
+ layer.setProperties(
+ lineJoin(Property.LINE_JOIN_ROUND),
+ lineCap(Property.LINE_CAP_ROUND),
+ lineColor(Color.RED),
+ lineWidth(20f)
+ );
+
+ mapboxMap.addLayer(layer);
+
+ //Need to get a fresh handle
+ layer = mapboxMap.getLayerAs("terrainLayer");
+
+ //Make sure it's also applied after the fact
+ layer.setMinZoom(10);
+ layer.setMaxZoom(15);
+
+ layer = (LineLayer) mapboxMap.getLayer("terrainLayer");
+ Toast.makeText(this, String.format(
+ "Set min/max zoom to %s - %s", layer.getMinZoom(), layer.getMaxZoom()), Toast.LENGTH_SHORT).show();
+ }
+
+ private void addSatelliteLayer() {
+ //Add a source
+ Source source = new RasterSource("my-raster-source", "mapbox://mapbox.satellite", 512);
+ mapboxMap.addSource(source);
+
+ //Add a layer
+ mapboxMap.addLayer(new RasterLayer("satellite-layer", "my-raster-source"));
+ }
+
+ private void updateWaterColorOnZoom() {
+ FillLayer layer = mapboxMap.getLayerAs("water");
+ if (layer == null) {
+ return;
}
- private void animateParksSource(final FeatureCollection parks, final int counter) {
- Handler handler = new Handler(getMainLooper());
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (mapboxMap == null) {
- return;
- }
-
- Log.d(TAG, "Updating parks source");
- //change the source
- int park = counter < parks.getFeatures().size() - 1 ? counter : 0;
-
- GeoJsonSource source = mapboxMap.getSourceAs("dynamic-park-source");
-
- if (source == null) {
- Log.e(TAG, "Source not found");
- Toast.makeText(RuntimeStyleActivity.this, "Source not found", Toast.LENGTH_SHORT).show();
- return;
- }
-
- List<Feature> features = new ArrayList<>();
- features.add(parks.getFeatures().get(park));
- source.setGeoJson(FeatureCollection.fromFeatures(features));
-
- //Re-post
- animateParksSource(parks, park + 1);
- }
- }, counter == 0 ? 100 : 1000);
+ //Set a zoom function to update the color of the water
+ layer.setProperties(fillColor(zoom(0.8f,
+ stop(1, fillColor(Color.GREEN)),
+ stop(4, fillColor(Color.BLUE)),
+ stop(12, fillColor(Color.RED)),
+ stop(20, fillColor(Color.BLACK))
+ )));
+
+ //do some animations to show it off properly
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(1), 1500);
+
+ PropertyValue<String> fillColor = layer.getFillColor();
+ Function<String> function = fillColor.getFunction();
+ if (function != null) {
+ Timber.d("Fill color base: " + function.getBase());
+ Timber.d("Fill color #stops: " + function.getStops().length);
+ if (function.getStops() != null) {
+ for (Stop stop : function.getStops()) {
+ Timber.d("Fill color #stops: " + stop);
+ }
+ }
+ }
+ }
+
+ private String readRawResource(@RawRes int rawResource) throws IOException {
+ InputStream is = getResources().openRawResource(rawResource);
+ Writer writer = new StringWriter();
+ char[] buffer = new char[1024];
+ try {
+ Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+ int numRead;
+ while ((numRead = reader.read(buffer)) != -1) {
+ writer.write(buffer, 0, numRead);
+ }
+ } finally {
+ is.close();
}
- private void addTerrainLayer() {
- //Add a source
- Source source = new VectorSource("my-terrain-source", "mapbox://mapbox.mapbox-terrain-v2");
- mapboxMap.addSource(source);
-
- LineLayer layer = new LineLayer("terrainLayer", "my-terrain-source");
- layer.setSourceLayer("contour");
- layer.setProperties(
- lineJoin(Property.LINE_JOIN_ROUND),
- lineCap(Property.LINE_CAP_ROUND),
- lineColor(Color.RED),
- lineWidth(20f)
- );
-
- mapboxMap.addLayer(layer);
-
- //Need to get a fresh handle
- layer = mapboxMap.getLayerAs("terrainLayer");
+ return writer.toString();
+ }
- //Make sure it's also applied after the fact
- layer.setMinZoom(10);
- layer.setMaxZoom(15);
+ private void setupActionBar() {
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- layer = (LineLayer) mapboxMap.getLayer("terrainLayer");
- Toast.makeText(this, String.format(
- "Set min/max zoom to %s - %s", layer.getMinZoom(), layer.getMaxZoom()), Toast.LENGTH_SHORT).show();
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
+ }
+
+ private void addCustomTileSource() {
+ //Add a source
+ Source source = new VectorSource("custom-tile-source", new TileSet("2.1.0", "https://vector.mapzen.com/osm/all/{z}/{x}/{y}.mvt?api_key=vector-tiles-LM25tq4"));
+ mapboxMap.addSource(source);
+
+ //Add a layer
+ mapboxMap.addLayer(
+ new FillLayer("custom-tile-layers", "custom-tile-source")
+ .withSourceLayer("water")
+ );
+ }
+
+ private void styleFillFilterLayer() {
+ mapboxMap.setStyleUrl("asset://fill_filter_style.json");
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(31, -100), 3));
+
+ Handler handler = new Handler(getMainLooper());
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (mapboxMap == null) {
+ return;
+ }
- private void addSatelliteLayer() {
- //Add a source
- Source source = new RasterSource("my-raster-source", "mapbox://mapbox.satellite", 512);
- mapboxMap.addSource(source);
+ Timber.d("Styling filtered fill layer");
- //Add a layer
- mapboxMap.addLayer(new RasterLayer("satellite-layer", "my-raster-source"));
- }
+ FillLayer states = (FillLayer) mapboxMap.getLayer("states");
- private void updateWaterColorOnZoom() {
- FillLayer layer = mapboxMap.getLayerAs("water");
- if (layer == null) {
- return;
- }
+ if (states != null) {
+ states.setFilter(eq("name", "Texas"));
- //Set a zoom function to update the color of the water
- layer.setProperties(fillColor(zoom(0.8f,
- stop(1, fillColor(Color.GREEN)),
- stop(4, fillColor(Color.BLUE)),
- stop(12, fillColor(Color.RED)),
- stop(20, fillColor(Color.BLACK))
- )));
-
- //do some animations to show it off properly
- mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(1), 1500);
-
- PropertyValue<String> fillColor = layer.getFillColor();
- Function<String> function = fillColor.getFunction();
- if (function != null) {
- Log.d(TAG, "Fill color base: " + function.getBase());
- Log.d(TAG, "Fill color #stops: " + function.getStops().length);
- if (function.getStops() != null) {
- for (Stop stop : function.getStops()) {
- Log.d(TAG, "Fill color #stops: " + stop);
- }
- }
+ states.setProperties(
+ fillColor(Color.RED),
+ fillOpacity(0.25f)
+ );
+ } else {
+ Toast.makeText(RuntimeStyleActivity.this, "No states layer in this style", Toast.LENGTH_SHORT).show();
}
- }
-
- private String readRawResource(@RawRes int rawResource) throws IOException {
- InputStream is = getResources().openRawResource(rawResource);
- Writer writer = new StringWriter();
- char[] buffer = new char[1024];
- try {
- Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
- int n;
- while ((n = reader.read(buffer)) != -1) {
- writer.write(buffer, 0, n);
- }
- } finally {
- is.close();
+ }
+ }, 2000);
+ }
+
+ private void styleLineFilterLayer() {
+ mapboxMap.setStyleUrl("asset://line_filter_style.json");
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(40, -97), 5));
+
+ Handler handler = new Handler(getMainLooper());
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (mapboxMap == null) {
+ return;
}
- return writer.toString();
- }
+ Timber.d("Styling filtered line layer");
+
+ LineLayer counties = (LineLayer) mapboxMap.getLayer("counties");
- private void setupActionBar() {
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ if (counties != null) {
+ counties.setFilter(eq("NAME10", "Washington"));
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
+ counties.setProperties(
+ lineColor(Color.RED),
+ lineOpacity(0.75f),
+ lineWidth(5f)
+ );
+ } else {
+ Toast.makeText(RuntimeStyleActivity.this, "No counties layer in this style", Toast.LENGTH_SHORT).show();
+ }
+ }
+ }, 2000);
+ }
+
+ private void styleNumericFillLayer() {
+ mapboxMap.setStyleUrl("asset://numeric_filter_style.json");
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(40, -97), 5));
+
+ Handler handler = new Handler(getMainLooper());
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (mapboxMap == null) {
+ return;
}
- }
- private void addCustomTileSource() {
- //Add a source
- Source source = new VectorSource("custom-tile-source", new TileSet("2.1.0", "https://vector.mapzen.com/osm/all/{z}/{x}/{y}.mvt?api_key=vector-tiles-LM25tq4"));
- mapboxMap.addSource(source);
+ Timber.d("Styling numeric fill layer");
- //Add a layer
- mapboxMap.addLayer(
- new FillLayer("custom-tile-layers", "custom-tile-source")
- .withSourceLayer("water")
- );
- }
+ FillLayer regions = (FillLayer) mapboxMap.getLayer("regions");
- private void styleFillFilterLayer() {
- mapboxMap.setStyleUrl("asset://fill_filter_style.json");
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(31, -100), 3));
-
- Handler handler = new Handler(getMainLooper());
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (mapboxMap == null) {
- return;
- }
-
- Log.d(TAG, "Styling filtered fill layer");
-
- FillLayer states = (FillLayer) mapboxMap.getLayer("states");
-
- if (states != null) {
- states.setFilter(eq("name", "Texas"));
-
- states.setProperties(
- fillColor(Color.RED),
- fillOpacity(0.25f)
- );
- } else {
- Toast.makeText(RuntimeStyleActivity.this, "No states layer in this style", Toast.LENGTH_SHORT).show();
- }
- }
- }, 2000);
- }
+ if (regions != null) {
+ regions.setFilter(all(gte("HRRNUM", 200), lt("HRRNUM", 300)));
- private void styleLineFilterLayer() {
- mapboxMap.setStyleUrl("asset://line_filter_style.json");
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(40, -97), 5));
-
- Handler handler = new Handler(getMainLooper());
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (mapboxMap == null) {
- return;
- }
-
- Log.d(TAG, "Styling filtered line layer");
-
- LineLayer counties = (LineLayer) mapboxMap.getLayer("counties");
-
- if (counties != null) {
- counties.setFilter(eq("NAME10", "Washington"));
-
- counties.setProperties(
- lineColor(Color.RED),
- lineOpacity(0.75f),
- lineWidth(5f)
- );
- } else {
- Toast.makeText(RuntimeStyleActivity.this, "No counties layer in this style", Toast.LENGTH_SHORT).show();
- }
- }
- }, 2000);
- }
-
- private void styleNumericFillLayer() {
- mapboxMap.setStyleUrl("asset://numeric_filter_style.json");
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(40, -97), 5));
-
- Handler handler = new Handler(getMainLooper());
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (mapboxMap == null) {
- return;
- }
-
- Log.d(TAG, "Styling numeric fill layer");
-
- FillLayer regions = (FillLayer) mapboxMap.getLayer("regions");
-
- if (regions != null) {
- regions.setFilter(all(gte("HRRNUM", 200), lt("HRRNUM", 300)));
-
- regions.setProperties(
- fillColor(Color.BLUE),
- fillOpacity(0.5f)
- );
- } else {
- Toast.makeText(RuntimeStyleActivity.this, "No regions layer in this style", Toast.LENGTH_SHORT).show();
- }
- }
- }, 2000);
- }
+ regions.setProperties(
+ fillColor(Color.BLUE),
+ fillOpacity(0.5f)
+ );
+ } else {
+ Toast.makeText(RuntimeStyleActivity.this, "No regions layer in this style", Toast.LENGTH_SHORT).show();
+ }
+ }
+ }, 2000);
+ }
- private static class DefaultCallback implements MapboxMap.CancelableCallback {
+ private static class DefaultCallback implements MapboxMap.CancelableCallback {
- @Override
- public void onCancel() {
- //noop
- }
+ @Override
+ public void onCancel() {
+ //noop
+ }
- @Override
- public void onFinish() {
- //noop
- }
+ @Override
+ public void onFinish() {
+ //noop
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTestActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTestActivity.java
index 6f04852ca1..1d242359bc 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTestActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTestActivity.java
@@ -12,58 +12,69 @@ import com.mapbox.mapboxsdk.testapp.R;
* Test activity for unit test execution
*/
public class RuntimeStyleTestActivity extends AppCompatActivity {
- private static final String TAG = RuntimeStyleTestActivity.class.getSimpleName();
- public MapView mapView;
- private MapboxMap mapboxMap;
+ public MapView mapView;
+ private MapboxMap mapboxMap;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_runtime_style);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_runtime_style);
- //Initialize map as normal
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap mapboxMap) {
- RuntimeStyleTestActivity.this.mapboxMap = mapboxMap;
- }
- });
- }
+ //Initialize map as normal
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap mapboxMap) {
+ RuntimeStyleTestActivity.this.mapboxMap = mapboxMap;
+ }
+ });
+ }
- public MapboxMap getMapboxMap() {
- return mapboxMap;
- }
+ public MapboxMap getMapboxMap() {
+ return mapboxMap;
+ }
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTimingTestActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTimingTestActivity.java
index 83378148ae..c57bc0069a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTimingTestActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTimingTestActivity.java
@@ -20,70 +20,81 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
* Test activity for unit test execution
*/
public class RuntimeStyleTimingTestActivity extends AppCompatActivity {
- private static final String TAG = RuntimeStyleTimingTestActivity.class.getSimpleName();
-
- public MapView mapView;
- private MapboxMap mapboxMap;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_runtime_style);
-
- //Initialize map as normal
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap mapboxMap) {
- RuntimeStyleTimingTestActivity.this.mapboxMap = mapboxMap;
- VectorSource museums = new VectorSource("museums_source", "mapbox://mapbox.2opop9hr");
- mapboxMap.addSource(museums);
-
- CircleLayer museumsLayer = new CircleLayer("museums", "museums_source");
- museumsLayer.setSourceLayer("museum-cusco");
- museumsLayer.setProperties(
- visibility(VISIBLE),
- circleRadius(8f),
- circleColor(Color.argb(1, 55, 148, 179))
- );
-
- mapboxMap.addLayer(museumsLayer);
- }
- });
- }
-
- public MapboxMap getMapboxMap() {
- return mapboxMap;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
+
+ public MapView mapView;
+ private MapboxMap mapboxMap;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_runtime_style);
+
+ //Initialize map as normal
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap mapboxMap) {
+ RuntimeStyleTimingTestActivity.this.mapboxMap = mapboxMap;
+ VectorSource museums = new VectorSource("museums_source", "mapbox://mapbox.2opop9hr");
+ mapboxMap.addSource(museums);
+
+ CircleLayer museumsLayer = new CircleLayer("museums", "museums_source");
+ museumsLayer.setSourceLayer("museum-cusco");
+ museumsLayer.setProperties(
+ visibility(VISIBLE),
+ circleRadius(8f),
+ circleColor(Color.argb(1, 55, 148, 179))
+ );
+
+ mapboxMap.addLayer(museumsLayer);
+ }
+ });
+ }
+
+ public MapboxMap getMapboxMap() {
+ return mapboxMap;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java
index aa739be229..73e6bc985a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java
@@ -9,7 +9,6 @@ import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
@@ -30,14 +29,12 @@ import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius;
+import timber.log.Timber;
/**
* Example on how to use a file:// resource for the style.json
*/
public class StyleFileActivity extends AppCompatActivity {
- private static final String TAG = StyleFileActivity.class.getSimpleName();
private MapboxMap mapboxMap;
private MapView mapView;
@@ -68,7 +65,7 @@ public class StyleFileActivity extends AppCompatActivity {
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- Log.i(TAG, "Loading style file");
+ Timber.i("Loading style file");
new CreateStyleFileTask().execute();
}
});
@@ -87,12 +84,12 @@ public class StyleFileActivity extends AppCompatActivity {
try {
cacheStyleFile = File.createTempFile("my-", ".style.json");
cacheStyleFile.createNewFile();
- Log.i(TAG, "Writing style file to: " + cacheStyleFile.getAbsolutePath());
+ Timber.i("Writing style file to: " + cacheStyleFile.getAbsolutePath());
writeToFile(cacheStyleFile, readRawResource(R.raw.local_style));
- } catch (Exception e) {
+ } catch (Exception exception) {
Toast.makeText(StyleFileActivity.this, "Could not create style file in cache dir", Toast.LENGTH_SHORT).show();
}
- return 1l;
+ return 1L;
}
protected void onPostExecute(Long result) {
@@ -106,9 +103,9 @@ public class StyleFileActivity extends AppCompatActivity {
char[] buffer = new char[1024];
try {
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
- int n;
- while ((n = reader.read(buffer)) != -1) {
- writer.write(buffer, 0, n);
+ int numRead;
+ while ((numRead = reader.read(buffer)) != -1) {
+ writer.write(buffer, 0, numRead);
}
} finally {
is.close();
@@ -131,18 +128,30 @@ public class StyleFileActivity extends AppCompatActivity {
}
@Override
- public void onResume() {
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
- public void onPause() {
+ protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java
new file mode 100644
index 0000000000..be71e58eba
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java
@@ -0,0 +1,215 @@
+package com.mapbox.mapboxsdk.testapp.activity.style;
+
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
+import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.services.commons.geojson.Feature;
+import com.mapbox.services.commons.geojson.FeatureCollection;
+import com.mapbox.services.commons.geojson.Point;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textFont;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textSize;
+
+/**
+ * Example to test runtime manipulation of symbol layers
+ */
+public class SymbolLayerActivity extends AppCompatActivity implements MapboxMap.OnMapClickListener {
+
+ public static final String MARKER_SOURCE = "marker-source";
+ public static final String MARKER_LAYER = "marker-layer";
+ private MapboxMap mapboxMap;
+ private MapView mapView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_symbollayer);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull final MapboxMap map) {
+ mapboxMap = map;
+
+ //Add a image for the makers
+ mapboxMap.addImage(
+ "my-marker-image",
+ BitmapFactory.decodeResource(SymbolLayerActivity.this.getResources(),
+ R.drawable.mapbox_marker_icon_default)
+ );
+
+ //Add a source
+ FeatureCollection markers = FeatureCollection.fromFeatures(new Feature[] {
+ Feature.fromGeometry(Point.fromCoordinates(new double[] {4.91638, 52.35673}), featureProperties("Marker 1")),
+ Feature.fromGeometry(Point.fromCoordinates(new double[] {4.91638, 52.34673}), featureProperties("Marker 2"))
+ });
+ mapboxMap.addSource(new GeoJsonSource(MARKER_SOURCE, markers));
+
+ //Add the symbol-layer
+ mapboxMap.addLayer(
+ new SymbolLayer(MARKER_LAYER, MARKER_SOURCE)
+ .withProperties(
+ iconImage("my-marker-image"),
+ iconAllowOverlap(true),
+ textField("{title}"),
+ textColor(Color.RED),
+ textSize(10f)
+ )
+ );
+
+ //Show
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.35273, 4.91638), 14));
+
+ //Set a click-listener so we can manipulate the map
+ mapboxMap.setOnMapClickListener(SymbolLayerActivity.this);
+ }
+ });
+ }
+
+ @Override
+ public void onMapClick(@NonNull LatLng point) {
+ //Query which features are clicked
+ PointF screenLoc = mapboxMap.getProjection().toScreenLocation(point);
+ List<Feature> features = mapboxMap.queryRenderedFeatures(screenLoc, MARKER_LAYER);
+
+ SymbolLayer layer = mapboxMap.getLayerAs(MARKER_LAYER);
+ if (features.size() == 0) {
+ //Reset
+ layer.setProperties(iconSize(1f));
+ } else {
+ layer.setProperties(iconSize(3f));
+ }
+ }
+
+ private void toggleTextSize() {
+ SymbolLayer layer = mapboxMap.getLayerAs(MARKER_LAYER);
+ layer.setProperties(layer.getTextSize().getValue() > 10 ? textSize(10f) : textSize(20f));
+ }
+
+ private void toggleTextField() {
+ SymbolLayer layer = mapboxMap.getLayerAs(MARKER_LAYER);
+ layer.setProperties("{title}".equals(layer.getTextField().getValue()) ? textField("āA") : textField("{title}"));
+ }
+
+ private void toggleTextFont() {
+ SymbolLayer layer = mapboxMap.getLayerAs(MARKER_LAYER);
+
+ String[] fonts = layer.getTextFont().getValue();
+ if (fonts == null || fonts.length == 0 || Arrays.asList(fonts).contains("Arial Unicode MS Regular")) {
+ layer.setProperties(textFont(new String[] {"DIN Offc Pro Bold", "Arial Unicode MS Bold"}));
+ } else {
+ layer.setProperties(textFont(new String[] {"DIN Offc Pro Medium", "Arial Unicode MS Regular"}));
+ }
+ }
+
+ private JsonObject featureProperties(String title) {
+ JsonObject object = new JsonObject();
+ object.add("title", new JsonPrimitive(title));
+ return object;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_symbol_layer, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.action_toggle_text_size:
+ toggleTextSize();
+ return true;
+ case R.id.action_toggle_text_field:
+ toggleTextField();
+ return true;
+ case R.id.action_toggle_text_font:
+ toggleTextFont();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java
index 301636611c..e20455b1ce 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java
@@ -29,142 +29,154 @@ import com.mapbox.mapboxsdk.testapp.R;
public class MyLocationDrawableActivity extends AppCompatActivity implements LocationListener {
- private static final int PERMISSIONS_LOCATION = 0;
-
- private MapView mapView;
- private MapboxMap mapboxMap;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_my_location_customization);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- findViewById(R.id.progress).setVisibility(View.GONE);
-
- MapboxMapOptions mapboxMapOptions = new MapboxMapOptions();
- mapboxMapOptions.styleUrl(Style.MAPBOX_STREETS);
-
- // configure MyLocationView drawables
- mapboxMapOptions.myLocationForegroundDrawable(ContextCompat.getDrawable(this, R.drawable.ic_chelsea));
- mapboxMapOptions.myLocationBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.ic_arsenal));
- mapboxMapOptions.myLocationForegroundTintColor(Color.GREEN);
- mapboxMapOptions.myLocationBackgroundTintColor(Color.YELLOW);
- mapboxMapOptions.myLocationBackgroundPadding(new int[]{0, 0,
- (int) getResources().getDimension(R.dimen.locationview_background_drawable_padding),
- (int) getResources().getDimension(R.dimen.locationview_background_drawable_padding)});
-
- mapboxMapOptions.myLocationAccuracyTint(Color.RED);
- mapboxMapOptions.myLocationAccuracyAlpha(155);
-
- mapView = new MapView(this, mapboxMapOptions);
- mapView.setId(R.id.mapView);
- ViewGroup parent = (ViewGroup) findViewById(R.id.container);
- parent.addView(mapView);
-
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- toggleGps(true);
- }
- });
+ private static final int PERMISSIONS_LOCATION = 0;
+
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_my_location_customization);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- public void toggleGps(boolean enableGps) {
- if (enableGps) {
- if ((ContextCompat.checkSelfPermission(this,
- Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
- || (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED)) {
- ActivityCompat.requestPermissions(this, new String[]{
- Manifest.permission.ACCESS_COARSE_LOCATION,
- Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
- } else {
- enableLocation(true);
- }
- } else {
- enableLocation(false);
- }
+ findViewById(R.id.progress).setVisibility(View.GONE);
+
+ MapboxMapOptions mapboxMapOptions = new MapboxMapOptions();
+ mapboxMapOptions.styleUrl(Style.MAPBOX_STREETS);
+
+ // configure MyLocationView drawables
+ mapboxMapOptions.myLocationForegroundDrawable(ContextCompat.getDrawable(this, R.drawable.ic_chelsea));
+ mapboxMapOptions.myLocationBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.ic_arsenal));
+ mapboxMapOptions.myLocationForegroundTintColor(Color.GREEN);
+ mapboxMapOptions.myLocationBackgroundTintColor(Color.YELLOW);
+ mapboxMapOptions.myLocationBackgroundPadding(new int[] {0, 0,
+ (int) getResources().getDimension(R.dimen.locationview_background_drawable_padding),
+ (int) getResources().getDimension(R.dimen.locationview_background_drawable_padding)});
+
+ mapboxMapOptions.myLocationAccuracyTint(Color.RED);
+ mapboxMapOptions.myLocationAccuracyAlpha(155);
+
+ mapView = new MapView(this, mapboxMapOptions);
+ mapView.setId(R.id.mapView);
+ ViewGroup parent = (ViewGroup) findViewById(R.id.container);
+ parent.addView(mapView);
+
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ toggleGps(true);
+ }
+ });
+ }
+
+ public void toggleGps(boolean enableGps) {
+ if (enableGps) {
+ if ((ContextCompat.checkSelfPermission(this,
+ Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
+ || (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED)) {
+ ActivityCompat.requestPermissions(this, new String[] {
+ Manifest.permission.ACCESS_COARSE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
+ } else {
+ enableLocation(true);
+ }
+ } else {
+ enableLocation(false);
}
-
- private void enableLocation(boolean enabled) {
- if (enabled) {
- mapboxMap.setMyLocationEnabled(true);
- Location location = mapboxMap.getMyLocation();
- if (location != null) {
- onLocationChanged(location);
- } else {
- LocationServices.getLocationServices(this).addLocationListener(this);
- }
- } else {
- mapboxMap.setMyLocationEnabled(false);
- }
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- if (requestCode == PERMISSIONS_LOCATION) {
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- enableLocation(true);
- }
- }
+ }
+
+ private void enableLocation(boolean enabled) {
+ if (enabled) {
+ mapboxMap.setMyLocationEnabled(true);
+ Location location = mapboxMap.getMyLocation();
+ if (location != null) {
+ onLocationChanged(location);
+ } else {
+ LocationServices.getLocationServices(this).addLocationListener(this);
+ }
+ } else {
+ mapboxMap.setMyLocationEnabled(false);
}
-
- @Override
- public void onLocationChanged(Location location) {
- if (mapboxMap != null) {
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 14));
- }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ if (requestCode == PERMISSIONS_LOCATION) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ enableLocation(true);
+ }
}
+ }
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
+ @Override
+ public void onLocationChanged(Location location) {
+ if (mapboxMap != null) {
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 14));
}
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java
index 929c2f0b75..2da3bedcbf 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java
@@ -3,6 +3,7 @@ package com.mapbox.mapboxsdk.testapp.activity.userlocation;
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
+import android.graphics.Color;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.IdRes;
@@ -31,200 +32,217 @@ import com.mapbox.mapboxsdk.testapp.R;
public class MyLocationTintActivity extends AppCompatActivity implements LocationListener {
- private MapView mapView;
- private MapboxMap mapboxMap;
- private boolean firstRun;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private boolean firstRun;
- private static final int PERMISSIONS_LOCATION = 0;
+ private static final int PERMISSIONS_LOCATION = 0;
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_my_location_dot_color);
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_my_location_dot_color);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+
+ // enable location updates
+ toggleGps(!mapboxMap.isMyLocationEnabled());
+
+ // add some padding
+ final MyLocationViewSettings myLocationViewSettings = mapboxMap.getMyLocationViewSettings();
+ myLocationViewSettings.setPadding(0, 500, 0, 0);
+
+ // enable tracking
+ TrackingSettings settings = mapboxMap.getTrackingSettings();
+ settings.setDismissLocationTrackingOnGesture(false);
+ settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
+
+ // handle default button clicks
+ ViewUtils.attachClickListener(
+ MyLocationTintActivity.this,
+ R.id.default_user_dot_coloring_button,
+ new View.OnClickListener() {
@Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
-
- // enable location updates
- toggleGps(!mapboxMap.isMyLocationEnabled());
-
- // add some padding
- final MyLocationViewSettings myLocationViewSettings = mapboxMap.getMyLocationViewSettings();
- myLocationViewSettings.setPadding(0, 500, 0, 0);
-
- // enable tracking
- TrackingSettings settings = mapboxMap.getTrackingSettings();
- settings.setDismissLocationTrackingOnGesture(false);
- settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
-
- // handle default button clicks
- ViewUtils.attachClickListener(
- MyLocationTintActivity.this,
- R.id.default_user_dot_coloring_button,
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- myLocationViewSettings.setAccuracyTintColor(ContextCompat.getColor(
- MyLocationTintActivity.this, R.color.my_location_ring));
- myLocationViewSettings.setForegroundTintColor(ContextCompat.getColor(
- MyLocationTintActivity.this, R.color.mapbox_blue));
- }
- });
-
- // handle tint user dot button clicks
- ViewUtils.attachClickListener(
- MyLocationTintActivity.this,
- R.id.tint_user_dot_button,
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- myLocationViewSettings.setAccuracyTintColor(
- ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_green));
- myLocationViewSettings.setForegroundTintColor(
- ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_green));
- }
- });
-
- // handle tint accuracy ring button clicks
- ViewUtils.attachClickListener(
- MyLocationTintActivity.this,
- R.id.user_accuracy_ring_tint_button,
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- myLocationViewSettings.setAccuracyTintColor(
- ContextCompat.getColor(MyLocationTintActivity.this, R.color.accent));
- myLocationViewSettings.setForegroundTintColor(
- ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_blue));
- }
- });
+ public void onClick(View view) {
+ myLocationViewSettings.setAccuracyTintColor(ContextCompat.getColor(
+ MyLocationTintActivity.this, R.color.mapbox_blue));
+ myLocationViewSettings.setForegroundTintColor(ContextCompat.getColor(
+ MyLocationTintActivity.this, R.color.mapbox_blue));
+ myLocationViewSettings.setBackgroundTintColor(Color.WHITE);
}
- });
-
- }
-
- @Override
- public void onLocationChanged(Location location) {
- if (mapboxMap != null && firstRun) {
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 15));
- firstRun = false;
- }
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- LocationServices.getLocationServices(this).addLocationListener(this);
- }
+ });
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- LocationServices.getLocationServices(this).removeLocationListener(this);
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
+ // handle tint user dot button clicks
+ ViewUtils.attachClickListener(
+ MyLocationTintActivity.this,
+ R.id.tint_user_dot_button,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ myLocationViewSettings.setAccuracyTintColor(
+ ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_green));
+ myLocationViewSettings.setForegroundTintColor(
+ ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_green));
+ myLocationViewSettings.setBackgroundTintColor(Color.WHITE);
+ }
+ });
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ // handle tint accuracy ring button clicks
+ ViewUtils.attachClickListener(
+ MyLocationTintActivity.this,
+ R.id.user_accuracy_ring_tint_button,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ myLocationViewSettings.setAccuracyTintColor(
+ ContextCompat.getColor(MyLocationTintActivity.this, R.color.accent));
+ myLocationViewSettings.setForegroundTintColor(
+ ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_blue));
+ myLocationViewSettings.setBackgroundTintColor(Color.WHITE);
+ }
+ });
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ ViewUtils.attachClickListener(
+ MyLocationTintActivity.this,
+ R.id.user_dot_transparent_button,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ myLocationViewSettings.setForegroundTintColor(Color.TRANSPARENT);
+ myLocationViewSettings.setBackgroundTintColor(Color.TRANSPARENT);
+ }
+ }
+ );
+ }
+ });
+
+ }
+
+ @Override
+ public void onLocationChanged(Location location) {
+ if (mapboxMap != null && firstRun) {
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 15));
+ firstRun = false;
}
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ LocationServices.getLocationServices(this).addLocationListener(this);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ LocationServices.getLocationServices(this).removeLocationListener(this);
+ mapView.onStop();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
-
- @UiThread
- public void toggleGps(boolean enableGps) {
- if (enableGps) {
- if ((ContextCompat.checkSelfPermission(this,
- Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
- || (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED)) {
- ActivityCompat.requestPermissions(this, new String[]{
- Manifest.permission.ACCESS_COARSE_LOCATION,
- Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
- } else {
- enableLocation(true);
- }
- } else {
- enableLocation(false);
- }
+ }
+
+ @UiThread
+ public void toggleGps(boolean enableGps) {
+ if (enableGps) {
+ if ((ContextCompat.checkSelfPermission(this,
+ Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
+ || (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED)) {
+ ActivityCompat.requestPermissions(this, new String[] {
+ Manifest.permission.ACCESS_COARSE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
+ } else {
+ enableLocation(true);
+ }
+ } else {
+ enableLocation(false);
}
-
- private void enableLocation(boolean enabled) {
- if (enabled) {
- mapboxMap.setMyLocationEnabled(true);
- if (mapboxMap.getMyLocation() != null) {
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
- new LatLng(mapboxMap.getMyLocation().getLatitude(),
- mapboxMap.getMyLocation().getLongitude()), 15));
- }
- } else {
- mapboxMap.setMyLocationEnabled(false);
- }
+ }
+
+ private void enableLocation(boolean enabled) {
+ if (enabled) {
+ mapboxMap.setMyLocationEnabled(true);
+ if (mapboxMap.getMyLocation() != null) {
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
+ new LatLng(mapboxMap.getMyLocation().getLatitude(),
+ mapboxMap.getMyLocation().getLongitude()), 15));
+ }
+ } else {
+ mapboxMap.setMyLocationEnabled(false);
}
-
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- if (requestCode == PERMISSIONS_LOCATION) {
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- enableLocation(true);
- }
- }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ if (requestCode == PERMISSIONS_LOCATION) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ enableLocation(true);
+ }
}
+ }
- private static class ViewUtils {
+ private static class ViewUtils {
- public static void attachClickListener(
- @NonNull Activity activity, @IdRes int buttonId, @Nullable View.OnClickListener clickListener) {
- View view = activity.findViewById(buttonId);
- if (view != null) {
- view.setOnClickListener(clickListener);
- }
- }
+ public static void attachClickListener(
+ @NonNull Activity activity, @IdRes int buttonId, @Nullable View.OnClickListener clickListener) {
+ View view = activity.findViewById(buttonId);
+ if (view != null) {
+ view.setOnClickListener(clickListener);
+ }
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java
index c2498223a2..e522840038 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java
@@ -15,6 +15,7 @@ import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
+
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
@@ -24,138 +25,150 @@ import com.mapbox.mapboxsdk.testapp.R;
public class MyLocationToggleActivity extends AppCompatActivity {
- private MapView mapView;
- private MapboxMap mapboxMap;
- private FloatingActionButton locationToggleFab;
-
- private static final int PERMISSIONS_LOCATION = 0;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_my_location_toggle);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayShowTitleEnabled(true);
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- }
- });
-
- locationToggleFab = (FloatingActionButton) findViewById(R.id.fabLocationToggle);
- locationToggleFab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- toggleGps(!mapboxMap.isMyLocationEnabled());
- }
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private FloatingActionButton locationToggleFab;
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
+ private static final int PERMISSIONS_LOCATION = 0;
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_my_location_toggle);
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayShowTitleEnabled(true);
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return false;
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ }
+ });
+
+ locationToggleFab = (FloatingActionButton) findViewById(R.id.fabLocationToggle);
+ locationToggleFab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (mapboxMap != null) {
+ toggleGps(!mapboxMap.isMyLocationEnabled());
}
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return false;
}
-
- @UiThread
- public void toggleGps(boolean enableGps) {
- if (enableGps) {
- if ((ContextCompat.checkSelfPermission(this,
- Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
- || (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED)) {
- ActivityCompat.requestPermissions(this, new String[]{
- Manifest.permission.ACCESS_COARSE_LOCATION,
- Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
- } else {
- enableLocation(true);
- }
- } else {
- enableLocation(false);
- }
+ }
+
+ @UiThread
+ public void toggleGps(boolean enableGps) {
+ if (enableGps) {
+ if ((ContextCompat.checkSelfPermission(this,
+ Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
+ || (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED)) {
+ ActivityCompat.requestPermissions(this, new String[] {
+ Manifest.permission.ACCESS_COARSE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
+ } else {
+ enableLocation(true);
+ }
+ } else {
+ enableLocation(false);
}
-
- private void enableLocation(boolean enabled) {
- if (enabled) {
- mapboxMap.setOnMyLocationChangeListener(new MapboxMap.OnMyLocationChangeListener() {
- @Override
- public void onMyLocationChange(@Nullable Location location) {
- if (location != null) {
- mapboxMap.setCameraPosition(new CameraPosition.Builder()
- .target(new LatLng(location))
- .zoom(16)
- .bearing(0)
- .tilt(0)
- .build());
- mapboxMap.setOnMyLocationChangeListener(null);
- }
- }
- });
- locationToggleFab.setImageResource(R.drawable.ic_location_disabled_24dp);
- } else {
- locationToggleFab.setImageResource(R.drawable.ic_my_location_24dp);
+ }
+
+ private void enableLocation(boolean enabled) {
+ if (enabled) {
+ mapboxMap.setOnMyLocationChangeListener(new MapboxMap.OnMyLocationChangeListener() {
+ @Override
+ public void onMyLocationChange(@Nullable Location location) {
+ if (location != null) {
+ mapboxMap.setCameraPosition(new CameraPosition.Builder()
+ .target(new LatLng(location))
+ .zoom(16)
+ .bearing(0)
+ .tilt(0)
+ .build());
+ mapboxMap.setOnMyLocationChangeListener(null);
+ }
}
-
- mapboxMap.setMyLocationEnabled(enabled);
+ });
+ locationToggleFab.setImageResource(R.drawable.ic_location_disabled_24dp);
+ } else {
+ locationToggleFab.setImageResource(R.drawable.ic_my_location_24dp);
}
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- if (requestCode == PERMISSIONS_LOCATION) {
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- enableLocation(true);
- }
- }
+ mapboxMap.setMyLocationEnabled(enabled);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ if (requestCode == PERMISSIONS_LOCATION) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ enableLocation(true);
+ }
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java
index 2c923a3ba9..3d08399abf 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java
@@ -34,308 +34,320 @@ import com.mapbox.mapboxsdk.maps.UiSettings;
import com.mapbox.mapboxsdk.testapp.R;
public class MyLocationTrackingModeActivity extends AppCompatActivity
- implements MapboxMap.OnMyLocationChangeListener, AdapterView.OnItemSelectedListener {
-
- public static final int TRACKING_NONE_INDEX = 0;
- public static final int TRACKING_FOLLOW_INDEX = 1;
- public static final int BEARING_NONE_INDEX = 0;
- public static final int BEARING_GPS_INDEX = 1;
- public static final int BEARING_COMPASS_INDEX = 2;
- private MapView mapView;
- private MapboxMap mapboxMap;
- private Spinner locationSpinner;
- private Spinner bearingSpinner;
- private Location location;
- private static final int PERMISSIONS_LOCATION = 0;
- private MenuItem dismissLocationTrackingOnGestureItem;
- private MenuItem dismissBearingTrackingOnGestureItem;
- private MenuItem enableRotateGesturesItem;
- private MenuItem enableScrollGesturesItem;
-
- @Override
- protected void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_my_location_tracking);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayShowTitleEnabled(false);
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- locationSpinner = (Spinner) findViewById(R.id.spinner_location);
- ArrayAdapter<CharSequence> locationTrackingAdapter = ArrayAdapter.createFromResource(
- actionBar.getThemedContext(), R.array.user_tracking_mode, android.R.layout.simple_spinner_item);
- locationTrackingAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- locationSpinner.setAdapter(locationTrackingAdapter);
-
- bearingSpinner = (Spinner) findViewById(R.id.spinner_bearing);
- ArrayAdapter<CharSequence> bearingTrackingAdapter = ArrayAdapter.createFromResource(
- actionBar.getThemedContext(), R.array.user_bearing_mode, android.R.layout.simple_spinner_item);
- bearingTrackingAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- bearingSpinner.setAdapter(bearingTrackingAdapter);
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
-
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- MyLocationTrackingModeActivity.this.mapboxMap = mapboxMap;
-
- locationSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
- bearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
- setCheckBoxes();
-
- mapboxMap.setOnMyLocationChangeListener(MyLocationTrackingModeActivity.this);
-
- mapboxMap.setOnMyLocationTrackingModeChangeListener(new MapboxMap.OnMyLocationTrackingModeChangeListener() {
- @Override
- public void onMyLocationTrackingModeChange(@MyLocationTracking.Mode int myLocationTrackingMode) {
- locationSpinner.setOnItemSelectedListener(null);
- switch (myLocationTrackingMode) {
- case MyLocationTracking.TRACKING_NONE:
- locationSpinner.setSelection(TRACKING_NONE_INDEX);
- break;
- case MyLocationTracking.TRACKING_FOLLOW:
- locationSpinner.setSelection(TRACKING_FOLLOW_INDEX);
- break;
- }
- locationSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
- }
- });
-
- mapboxMap.setOnMyBearingTrackingModeChangeListener(new MapboxMap.OnMyBearingTrackingModeChangeListener() {
- @Override
- public void onMyBearingTrackingModeChange(@MyBearingTracking.Mode int myBearingTrackingMode) {
- bearingSpinner.setOnItemSelectedListener(null);
- switch (myBearingTrackingMode) {
- case MyBearingTracking.NONE:
- bearingSpinner.setSelection(BEARING_NONE_INDEX);
- break;
-
- case MyBearingTracking.GPS:
- bearingSpinner.setSelection(BEARING_GPS_INDEX);
- break;
-
- case MyBearingTracking.COMPASS:
- bearingSpinner.setSelection(BEARING_COMPASS_INDEX);
- break;
- }
- bearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
- }
- });
-
- if (savedInstanceState == null) {
- toggleGps(true);
- }
- }
- });
+ implements MapboxMap.OnMyLocationChangeListener, AdapterView.OnItemSelectedListener {
+
+ public static final int TRACKING_NONE_INDEX = 0;
+ public static final int TRACKING_FOLLOW_INDEX = 1;
+ public static final int BEARING_NONE_INDEX = 0;
+ public static final int BEARING_GPS_INDEX = 1;
+ public static final int BEARING_COMPASS_INDEX = 2;
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private Spinner locationSpinner;
+ private Spinner bearingSpinner;
+ private Location location;
+ private static final int PERMISSIONS_LOCATION = 0;
+ private MenuItem dismissLocationTrackingOnGestureItem;
+ private MenuItem dismissBearingTrackingOnGestureItem;
+ private MenuItem enableRotateGesturesItem;
+ private MenuItem enableScrollGesturesItem;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_my_location_tracking);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayShowTitleEnabled(false);
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
}
- @UiThread
- public void toggleGps(boolean enableGps) {
- if (enableGps) {
- if ((ContextCompat.checkSelfPermission(this,
- Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
- || (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED)) {
- ActivityCompat.requestPermissions(this, new String[]{
- Manifest.permission.ACCESS_COARSE_LOCATION,
- Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
- } else {
- enableLocation(true);
- }
- } else {
- enableLocation(false);
- }
- }
+ locationSpinner = (Spinner) findViewById(R.id.spinner_location);
+ ArrayAdapter<CharSequence> locationTrackingAdapter = ArrayAdapter.createFromResource(
+ actionBar.getThemedContext(), R.array.user_tracking_mode, android.R.layout.simple_spinner_item);
+ locationTrackingAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ locationSpinner.setAdapter(locationTrackingAdapter);
- private void enableLocation(boolean enabled) {
- if (enabled) {
- mapboxMap.setMyLocationEnabled(true);
- Location location = mapboxMap.getMyLocation();
- if (location != null) {
- setInitialPosition(new LatLng(location));
- }
- } else {
- mapboxMap.setMyLocationEnabled(false);
- }
- }
+ bearingSpinner = (Spinner) findViewById(R.id.spinner_bearing);
+ ArrayAdapter<CharSequence> bearingTrackingAdapter = ArrayAdapter.createFromResource(
+ actionBar.getThemedContext(), R.array.user_bearing_mode, android.R.layout.simple_spinner_item);
+ bearingTrackingAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ bearingSpinner.setAdapter(bearingTrackingAdapter);
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- if (requestCode == PERMISSIONS_LOCATION) {
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- enableLocation(true);
- }
- }
- }
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
- private void setInitialPosition(LatLng latLng) {
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14));
- mapboxMap.setMyLocationEnabled(true);
- locationSpinner.setEnabled(true);
- bearingSpinner.setEnabled(true);
- }
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ MyLocationTrackingModeActivity.this.mapboxMap = mapboxMap;
+
+ locationSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
+ bearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
+ setCheckBoxes();
- @Override
- public void onMyLocationChange(@Nullable Location location) {
- if (location != null) {
- if (this.location == null) {
- // initial location to reposition map
- setInitialPosition(new LatLng(location));
+ mapboxMap.setOnMyLocationChangeListener(MyLocationTrackingModeActivity.this);
+
+ mapboxMap.setOnMyLocationTrackingModeChangeListener(new MapboxMap.OnMyLocationTrackingModeChangeListener() {
+ @Override
+ public void onMyLocationTrackingModeChange(@MyLocationTracking.Mode int myLocationTrackingMode) {
+ locationSpinner.setOnItemSelectedListener(null);
+ switch (myLocationTrackingMode) {
+ case MyLocationTracking.TRACKING_NONE:
+ locationSpinner.setSelection(TRACKING_NONE_INDEX);
+ break;
+ case MyLocationTracking.TRACKING_FOLLOW:
+ locationSpinner.setSelection(TRACKING_FOLLOW_INDEX);
+ break;
}
- this.location = location;
- showSnackBar();
- }
- }
+ locationSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
+ }
+ });
- private void showSnackBar() {
- String desc = "Loc Chg: ";
- boolean noInfo = true;
- if (location.hasSpeed()) {
- desc += String.format(MapboxConstants.MAPBOX_LOCALE, "Spd = %.1f km/h ", location.getSpeed() * 3.6f);
- noInfo = false;
- }
- if (location.hasAltitude()) {
- desc += String.format(MapboxConstants.MAPBOX_LOCALE, "Alt = %.0f m ", location.getAltitude());
- noInfo = false;
- }
- if (location.hasAccuracy()) {
- desc += String.format(MapboxConstants.MAPBOX_LOCALE, "Acc = %.0f m", location.getAccuracy());
- }
+ mapboxMap.setOnMyBearingTrackingModeChangeListener(new MapboxMap.OnMyBearingTrackingModeChangeListener() {
+ @Override
+ public void onMyBearingTrackingModeChange(@MyBearingTracking.Mode int myBearingTrackingMode) {
+ bearingSpinner.setOnItemSelectedListener(null);
+ switch (myBearingTrackingMode) {
+ case MyBearingTracking.NONE:
+ bearingSpinner.setSelection(BEARING_NONE_INDEX);
+ break;
+
+ case MyBearingTracking.GPS:
+ bearingSpinner.setSelection(BEARING_GPS_INDEX);
+ break;
+
+ case MyBearingTracking.COMPASS:
+ bearingSpinner.setSelection(BEARING_COMPASS_INDEX);
+ break;
+ }
+ bearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
+ }
+ });
- if (noInfo) {
- desc += "No extra info";
+ if (savedInstanceState == null) {
+ toggleGps(true);
}
- Snackbar.make(findViewById(android.R.id.content), desc, Snackbar.LENGTH_SHORT).show();
+ }
+ });
+ }
+
+ @UiThread
+ public void toggleGps(boolean enableGps) {
+ if (enableGps) {
+ if ((ContextCompat.checkSelfPermission(this,
+ Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
+ || (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED)) {
+ ActivityCompat.requestPermissions(this, new String[] {
+ Manifest.permission.ACCESS_COARSE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
+ } else {
+ enableLocation(true);
+ }
+ } else {
+ enableLocation(false);
}
-
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) throws SecurityException {
- TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
- if (parent.getId() == R.id.spinner_location) {
- switch (position) {
- case TRACKING_NONE_INDEX:
- trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE);
- break;
-
- case TRACKING_FOLLOW_INDEX:
- trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- break;
- }
- } else if (parent.getId() == R.id.spinner_bearing) {
- switch (position) {
- case BEARING_NONE_INDEX:
- trackingSettings.setMyBearingTrackingMode(MyBearingTracking.NONE);
- break;
-
- case BEARING_GPS_INDEX:
- trackingSettings.setMyBearingTrackingMode(MyBearingTracking.GPS);
- break;
-
- case BEARING_COMPASS_INDEX:
- trackingSettings.setMyBearingTrackingMode(MyBearingTracking.COMPASS);
- break;
- }
- }
+ }
+
+ private void enableLocation(boolean enabled) {
+ if (enabled) {
+ mapboxMap.setMyLocationEnabled(true);
+ Location location = mapboxMap.getMyLocation();
+ if (location != null) {
+ setInitialPosition(new LatLng(location));
+ }
+ } else {
+ mapboxMap.setMyLocationEnabled(false);
}
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
-
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ if (requestCode == PERMISSIONS_LOCATION) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ enableLocation(true);
+ }
}
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
+ }
+
+ private void setInitialPosition(LatLng latLng) {
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14));
+ mapboxMap.setMyLocationEnabled(true);
+ locationSpinner.setEnabled(true);
+ bearingSpinner.setEnabled(true);
+ }
+
+ @Override
+ public void onMyLocationChange(@Nullable Location location) {
+ if (location != null) {
+ if (this.location == null) {
+ // initial location to reposition map
+ setInitialPosition(new LatLng(location));
+ }
+ this.location = location;
+ showSnackBar();
}
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
+ }
+
+ private void showSnackBar() {
+ String desc = "Loc Chg: ";
+ boolean noInfo = true;
+ if (location.hasSpeed()) {
+ desc += String.format(MapboxConstants.MAPBOX_LOCALE, "Spd = %.1f km/h ", location.getSpeed() * 3.6f);
+ noInfo = false;
}
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
+ if (location.hasAltitude()) {
+ desc += String.format(MapboxConstants.MAPBOX_LOCALE, "Alt = %.0f m ", location.getAltitude());
+ noInfo = false;
}
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
+ if (location.hasAccuracy()) {
+ desc += String.format(MapboxConstants.MAPBOX_LOCALE, "Acc = %.0f m", location.getAccuracy());
}
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
+ if (noInfo) {
+ desc += "No extra info";
}
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_tracking, menu);
- dismissLocationTrackingOnGestureItem = menu.findItem(R.id.action_toggle_dismissible_location);
- dismissBearingTrackingOnGestureItem = menu.findItem(R.id.action_toggle_dismissible_bearing);
- enableRotateGesturesItem = menu.findItem(R.id.action_toggle_rotate_gesture_enabled);
- enableScrollGesturesItem = menu.findItem(R.id.action_toggle_scroll_gesture_enabled);
- setCheckBoxes();
- return true;
+ Snackbar.make(findViewById(android.R.id.content), desc, Snackbar.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) throws SecurityException {
+ TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
+ if (parent.getId() == R.id.spinner_location) {
+ switch (position) {
+ case TRACKING_NONE_INDEX:
+ trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE);
+ break;
+
+ case TRACKING_FOLLOW_INDEX:
+ trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
+ break;
+ }
+ } else if (parent.getId() == R.id.spinner_bearing) {
+ switch (position) {
+ case BEARING_NONE_INDEX:
+ trackingSettings.setMyBearingTrackingMode(MyBearingTracking.NONE);
+ break;
+
+ case BEARING_GPS_INDEX:
+ trackingSettings.setMyBearingTrackingMode(MyBearingTracking.GPS);
+ break;
+
+ case BEARING_COMPASS_INDEX:
+ trackingSettings.setMyBearingTrackingMode(MyBearingTracking.COMPASS);
+ break;
+ }
}
-
- private void setCheckBoxes() {
- if (mapboxMap != null && dismissBearingTrackingOnGestureItem != null) {
- TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
- UiSettings uiSettings = mapboxMap.getUiSettings();
- dismissBearingTrackingOnGestureItem.setChecked(trackingSettings.isDismissBearingTrackingOnGesture());
- dismissLocationTrackingOnGestureItem.setChecked(trackingSettings.isDismissLocationTrackingOnGesture());
- enableRotateGesturesItem.setChecked(uiSettings.isRotateGesturesEnabled());
- enableScrollGesturesItem.setChecked(uiSettings.isScrollGesturesEnabled());
- }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_tracking, menu);
+ dismissLocationTrackingOnGestureItem = menu.findItem(R.id.action_toggle_dismissible_location);
+ dismissBearingTrackingOnGestureItem = menu.findItem(R.id.action_toggle_dismissible_bearing);
+ enableRotateGesturesItem = menu.findItem(R.id.action_toggle_rotate_gesture_enabled);
+ enableScrollGesturesItem = menu.findItem(R.id.action_toggle_scroll_gesture_enabled);
+ setCheckBoxes();
+ return true;
+ }
+
+ private void setCheckBoxes() {
+ if (mapboxMap != null && dismissBearingTrackingOnGestureItem != null) {
+ TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
+ UiSettings uiSettings = mapboxMap.getUiSettings();
+ dismissBearingTrackingOnGestureItem.setChecked(trackingSettings.isDismissBearingTrackingOnGesture());
+ dismissLocationTrackingOnGestureItem.setChecked(trackingSettings.isDismissLocationTrackingOnGesture());
+ enableRotateGesturesItem.setChecked(uiSettings.isRotateGesturesEnabled());
+ enableScrollGesturesItem.setChecked(uiSettings.isScrollGesturesEnabled());
}
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- boolean state;
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- case R.id.action_toggle_dismissible_location:
- state = !item.isChecked();
- mapboxMap.getTrackingSettings().setDismissLocationTrackingOnGesture(state);
- Toast.makeText(this, "Dismiss tracking mode on gesture = " + state, Toast.LENGTH_SHORT).show();
- item.setChecked(state);
- return true;
- case R.id.action_toggle_dismissible_bearing:
- state = !item.isChecked();
- mapboxMap.getTrackingSettings().setDismissBearingTrackingOnGesture(state);
- Toast.makeText(this, "Dismiss bearing mode on gesture = " + state, Toast.LENGTH_SHORT).show();
- item.setChecked(state);
- return true;
- case R.id.action_toggle_rotate_gesture_enabled:
- state = !item.isChecked();
- mapboxMap.getUiSettings().setRotateGesturesEnabled(state);
- Toast.makeText(this, "Rotate gesture enabled = " + state, Toast.LENGTH_SHORT).show();
- item.setChecked(state);
- return true;
- case R.id.action_toggle_scroll_gesture_enabled:
- state = !item.isChecked();
- mapboxMap.getUiSettings().setScrollGesturesEnabled(state);
- Toast.makeText(this, "Scroll gesture enabled = " + state, Toast.LENGTH_SHORT).show();
- item.setChecked(state);
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ boolean state;
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.action_toggle_dismissible_location:
+ state = !item.isChecked();
+ mapboxMap.getTrackingSettings().setDismissLocationTrackingOnGesture(state);
+ Toast.makeText(this, "Dismiss tracking mode on gesture = " + state, Toast.LENGTH_SHORT).show();
+ item.setChecked(state);
+ return true;
+ case R.id.action_toggle_dismissible_bearing:
+ state = !item.isChecked();
+ mapboxMap.getTrackingSettings().setDismissBearingTrackingOnGesture(state);
+ Toast.makeText(this, "Dismiss bearing mode on gesture = " + state, Toast.LENGTH_SHORT).show();
+ item.setChecked(state);
+ return true;
+ case R.id.action_toggle_rotate_gesture_enabled:
+ state = !item.isChecked();
+ mapboxMap.getUiSettings().setRotateGesturesEnabled(state);
+ Toast.makeText(this, "Rotate gesture enabled = " + state, Toast.LENGTH_SHORT).show();
+ item.setChecked(state);
+ return true;
+ case R.id.action_toggle_scroll_gesture_enabled:
+ state = !item.isChecked();
+ mapboxMap.getUiSettings().setScrollGesturesEnabled(state);
+ Toast.makeText(this, "Scroll gesture enabled = " + state, Toast.LENGTH_SHORT).show();
+ item.setChecked(state);
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureAdapter.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureAdapter.java
index 71adba8ac7..a935c2134f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureAdapter.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureAdapter.java
@@ -15,41 +15,41 @@ import java.util.List;
public class FeatureAdapter extends RecyclerView.Adapter<FeatureAdapter.ViewHolder> {
- private List<Feature> features;
+ private List<Feature> features;
- public static class ViewHolder extends RecyclerView.ViewHolder {
+ public static class ViewHolder extends RecyclerView.ViewHolder {
- public TextView labelView;
- public TextView descriptionView;
+ public TextView labelView;
+ public TextView descriptionView;
- public ViewHolder(View view) {
- super(view);
- Typeface typeface = FontCache.get("Roboto-Regular.ttf",view.getContext());
- labelView = (TextView) view.findViewById(R.id.nameView);
- labelView.setTypeface(typeface);
- descriptionView = (TextView) view.findViewById(R.id.descriptionView);
- descriptionView.setTypeface(typeface);
- }
- }
-
- public FeatureAdapter(List<Feature> features) {
- this.features = features;
- }
-
- @Override
- public FeatureAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_main_feature, parent, false);
- return new ViewHolder(view);
- }
-
- @Override
- public void onBindViewHolder(ViewHolder holder, int position) {
- holder.labelView.setText(features.get(position).getLabel());
- holder.descriptionView.setText(features.get(position).getDescription());
- }
-
- @Override
- public int getItemCount() {
- return features.size();
+ public ViewHolder(View view) {
+ super(view);
+ Typeface typeface = FontCache.get("Roboto-Regular.ttf", view.getContext());
+ labelView = (TextView) view.findViewById(R.id.nameView);
+ labelView.setTypeface(typeface);
+ descriptionView = (TextView) view.findViewById(R.id.descriptionView);
+ descriptionView.setTypeface(typeface);
}
+ }
+
+ public FeatureAdapter(List<Feature> features) {
+ this.features = features;
+ }
+
+ @Override
+ public FeatureAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_main_feature, parent, false);
+ return new ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ holder.labelView.setText(features.get(position).getLabel());
+ holder.descriptionView.setText(features.get(position).getDescription());
+ }
+
+ @Override
+ public int getItemCount() {
+ return features.size();
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java
index d86e06ea6d..012bbed4ca 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java
@@ -18,161 +18,162 @@ import java.util.Comparator;
public class FeatureSectionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
- private static final int SECTION_TYPE = 0;
-
- private final Context context;
- private final SparseArray<Section> sections;
- private final RecyclerView.Adapter adapter;
-
- @LayoutRes
- private final int sectionRes;
-
- @IdRes
- private final int textRes;
-
- private boolean valid = true;
-
- public FeatureSectionAdapter(Context ctx, int sectionResourceId, int textResourceId, RecyclerView.Adapter baseAdapter) {
- context = ctx;
- sectionRes = sectionResourceId;
- textRes = textResourceId;
- adapter = baseAdapter;
- sections = new SparseArray<>();
- adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
- @Override
- public void onChanged() {
- valid = adapter.getItemCount() > 0;
- notifyDataSetChanged();
- }
-
- @Override
- public void onItemRangeChanged(int positionStart, int itemCount) {
- valid = adapter.getItemCount() > 0;
- notifyItemRangeChanged(positionStart, itemCount);
- }
-
- @Override
- public void onItemRangeInserted(int positionStart, int itemCount) {
- valid = adapter.getItemCount() > 0;
- notifyItemRangeInserted(positionStart, itemCount);
- }
-
- @Override
- public void onItemRangeRemoved(int positionStart, int itemCount) {
- valid = adapter.getItemCount() > 0;
- notifyItemRangeRemoved(positionStart, itemCount);
- }
- });
- }
+ private static final int SECTION_TYPE = 0;
+
+ private final Context context;
+ private final SparseArray<Section> sections;
+ private final RecyclerView.Adapter adapter;
+
+ @LayoutRes
+ private final int sectionRes;
+
+ @IdRes
+ private final int textRes;
+
+ private boolean valid = true;
+
+ public FeatureSectionAdapter(Context ctx, int sectionResourceId, int textResourceId,
+ RecyclerView.Adapter baseAdapter) {
+ context = ctx;
+ sectionRes = sectionResourceId;
+ textRes = textResourceId;
+ adapter = baseAdapter;
+ sections = new SparseArray<>();
+ adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
+ @Override
+ public void onChanged() {
+ valid = adapter.getItemCount() > 0;
+ notifyDataSetChanged();
+ }
+ @Override
+ public void onItemRangeChanged(int positionStart, int itemCount) {
+ valid = adapter.getItemCount() > 0;
+ notifyItemRangeChanged(positionStart, itemCount);
+ }
- public static class SectionViewHolder extends RecyclerView.ViewHolder {
+ @Override
+ public void onItemRangeInserted(int positionStart, int itemCount) {
+ valid = adapter.getItemCount() > 0;
+ notifyItemRangeInserted(positionStart, itemCount);
+ }
- public TextView title;
+ @Override
+ public void onItemRangeRemoved(int positionStart, int itemCount) {
+ valid = adapter.getItemCount() > 0;
+ notifyItemRangeRemoved(positionStart, itemCount);
+ }
+ });
+ }
- public SectionViewHolder(@NonNull View view, @IdRes int textRes) {
- super(view);
- title = (TextView) view.findViewById(textRes);
- title.setTypeface(FontCache.get("Roboto-Medium.ttf", view.getContext()));
- }
- }
- @Override
- public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int typeView) {
- if (typeView == SECTION_TYPE) {
- final View view = LayoutInflater.from(context).inflate(sectionRes, parent, false);
- return new SectionViewHolder(view, textRes);
- } else {
- return adapter.onCreateViewHolder(parent, typeView - 1);
- }
- }
+ public static class SectionViewHolder extends RecyclerView.ViewHolder {
- @Override
- public void onBindViewHolder(RecyclerView.ViewHolder sectionViewHolder, int position) {
- if (isSectionHeaderPosition(position)) {
- ((SectionViewHolder) sectionViewHolder).title.setText(sections.get(position).title);
- } else {
- adapter.onBindViewHolder(sectionViewHolder, getConvertedPosition(position));
- }
+ public TextView title;
+ public SectionViewHolder(@NonNull View view, @IdRes int textRes) {
+ super(view);
+ title = (TextView) view.findViewById(textRes);
+ title.setTypeface(FontCache.get("Roboto-Medium.ttf", view.getContext()));
}
-
- @Override
- public int getItemViewType(int position) {
- return isSectionHeaderPosition(position)
- ? SECTION_TYPE
- : adapter.getItemViewType(getConvertedPosition(position)) + 1;
+ }
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int typeView) {
+ if (typeView == SECTION_TYPE) {
+ final View view = LayoutInflater.from(context).inflate(sectionRes, parent, false);
+ return new SectionViewHolder(view, textRes);
+ } else {
+ return adapter.onCreateViewHolder(parent, typeView - 1);
}
-
-
- public static class Section {
- int firstPosition;
- int sectionedPosition;
- CharSequence title;
-
- public Section(int firstPosition, CharSequence title) {
- this.firstPosition = firstPosition;
- this.title = title;
- }
-
- public CharSequence getTitle() {
- return title;
- }
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder sectionViewHolder, int position) {
+ if (isSectionHeaderPosition(position)) {
+ ((SectionViewHolder) sectionViewHolder).title.setText(sections.get(position).title);
+ } else {
+ adapter.onBindViewHolder(sectionViewHolder, getConvertedPosition(position));
}
+ }
- public void setSections(Section[] sections) {
- this.sections.clear();
+ @Override
+ public int getItemViewType(int position) {
+ return isSectionHeaderPosition(position)
+ ? SECTION_TYPE
+ : adapter.getItemViewType(getConvertedPosition(position)) + 1;
+ }
- Arrays.sort(sections, new Comparator<Section>() {
- @Override
- public int compare(Section o, Section o1) {
- return (o.firstPosition == o1.firstPosition)
- ? 0
- : ((o.firstPosition < o1.firstPosition) ? -1 : 1);
- }
- });
- int offset = 0;
- for (Section section : sections) {
- section.sectionedPosition = section.firstPosition + offset;
- this.sections.append(section.sectionedPosition, section);
- ++offset;
- }
+ public static class Section {
+ int firstPosition;
+ int sectionedPosition;
+ CharSequence title;
- notifyDataSetChanged();
+ public Section(int firstPosition, CharSequence title) {
+ this.firstPosition = firstPosition;
+ this.title = title;
}
- public int getConvertedPosition(int sectionedPosition) {
- if (isSectionHeaderPosition(sectionedPosition)) {
- return RecyclerView.NO_POSITION;
- }
-
- int offset = 0;
- for (int i = 0; i < sections.size(); i++) {
- if (sections.valueAt(i).sectionedPosition > sectionedPosition) {
- break;
- }
- --offset;
- }
- return sectionedPosition + offset;
+ public CharSequence getTitle() {
+ return title;
}
-
- public boolean isSectionHeaderPosition(int position) {
- return sections.get(position) != null;
+ }
+
+
+ public void setSections(Section[] sections) {
+ this.sections.clear();
+
+ Arrays.sort(sections, new Comparator<Section>() {
+ @Override
+ public int compare(Section section, Section section1) {
+ return (section.firstPosition == section1.firstPosition)
+ ? 0
+ : ((section.firstPosition < section1.firstPosition) ? -1 : 1);
+ }
+ });
+
+ int offset = 0;
+ for (Section section : sections) {
+ section.sectionedPosition = section.firstPosition + offset;
+ this.sections.append(section.sectionedPosition, section);
+ ++offset;
}
+ notifyDataSetChanged();
+ }
- @Override
- public long getItemId(int position) {
- return isSectionHeaderPosition(position)
- ? Integer.MAX_VALUE - sections.indexOfKey(position)
- : adapter.getItemId(getConvertedPosition(position));
+ public int getConvertedPosition(int sectionedPosition) {
+ if (isSectionHeaderPosition(sectionedPosition)) {
+ return RecyclerView.NO_POSITION;
}
- @Override
- public int getItemCount() {
- return (valid ? adapter.getItemCount() + sections.size() : 0);
+ int offset = 0;
+ for (int i = 0; i < sections.size(); i++) {
+ if (sections.valueAt(i).sectionedPosition > sectionedPosition) {
+ break;
+ }
+ --offset;
}
+ return sectionedPosition + offset;
+ }
+
+ public boolean isSectionHeaderPosition(int position) {
+ return sections.get(position) != null;
+ }
+
+
+ @Override
+ public long getItemId(int position) {
+ return isSectionHeaderPosition(position)
+ ? Integer.MAX_VALUE - sections.indexOfKey(position)
+ : adapter.getItemId(getConvertedPosition(position));
+ }
+
+ @Override
+ public int getItemCount() {
+ return (valid ? adapter.getItemCount() + sections.size() : 0);
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/activity/Feature.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/activity/Feature.java
index a54e55529e..d745982388 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/activity/Feature.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/activity/Feature.java
@@ -5,73 +5,73 @@ import android.os.Parcelable;
public class Feature implements Parcelable {
- private String name;
- private String label;
- private String description;
- private String category;
- private boolean requiresLocationPermission;
+ private String name;
+ private String label;
+ private String description;
+ private String category;
+ private boolean requiresLocationPermission;
- public Feature(String name, String label, String description, String category, boolean requiresLocationPermission) {
- this.name = name;
- this.label = label;
- this.description = description;
- this.category = category;
- this.requiresLocationPermission = requiresLocationPermission;
- }
+ public Feature(String name, String label, String description, String category, boolean requiresLocationPermission) {
+ this.name = name;
+ this.label = label;
+ this.description = description;
+ this.category = category;
+ this.requiresLocationPermission = requiresLocationPermission;
+ }
- private Feature(Parcel in) {
- name = in.readString();
- label = in.readString();
- description = in.readString();
- category = in.readString();
- requiresLocationPermission = in.readByte() != 0;
- }
+ private Feature(Parcel in) {
+ name = in.readString();
+ label = in.readString();
+ description = in.readString();
+ category = in.readString();
+ requiresLocationPermission = in.readByte() != 0;
+ }
- public String getName() {
- return name;
- }
+ public String getName() {
+ return name;
+ }
- public String getSimpleName() {
- String[] split = name.split("\\.");
- return split[split.length - 1];
- }
+ public String getSimpleName() {
+ String[] split = name.split("\\.");
+ return split[split.length - 1];
+ }
- public String getLabel() {
- return label != null ? label : getSimpleName();
- }
+ public String getLabel() {
+ return label != null ? label : getSimpleName();
+ }
- public String getDescription() {
- return description != null ? description : "-";
- }
+ public String getDescription() {
+ return description != null ? description : "-";
+ }
- public String getCategory() {
- return category;
- }
+ public String getCategory() {
+ return category;
+ }
- public boolean isRequiresLocationPermission() {
- return requiresLocationPermission;
- }
+ public boolean isRequiresLocationPermission() {
+ return requiresLocationPermission;
+ }
- public int describeContents() {
- return 0;
- }
+ public int describeContents() {
+ return 0;
+ }
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(name);
- out.writeString(label);
- out.writeString(description);
- out.writeString(category);
- out.writeByte((byte) (requiresLocationPermission ? 1 : 0));
- }
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(name);
+ out.writeString(label);
+ out.writeString(description);
+ out.writeString(category);
+ out.writeByte((byte) (requiresLocationPermission ? 1 : 0));
+ }
- public static final Parcelable.Creator<Feature> CREATOR
- = new Parcelable.Creator<Feature>() {
- public Feature createFromParcel(Parcel in) {
- return new Feature(in);
- }
+ public static final Parcelable.Creator<Feature> CREATOR
+ = new Parcelable.Creator<Feature>() {
+ public Feature createFromParcel(Parcel in) {
+ return new Feature(in);
+ }
- public Feature[] newArray(int size) {
- return new Feature[size];
- }
+ public Feature[] newArray(int size) {
+ return new Feature[size];
+ }
};
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarker.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarker.java
index 4eabb0a3bb..3b9f67aa1e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarker.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarker.java
@@ -4,15 +4,15 @@ import com.mapbox.mapboxsdk.annotations.Marker;
public class CityStateMarker extends Marker {
- private String infoWindowBackgroundColor;
+ private String infoWindowBackgroundColor;
- public CityStateMarker(CityStateMarkerOptions cityStateOptions, String color) {
- super(cityStateOptions);
- infoWindowBackgroundColor = color;
- }
+ public CityStateMarker(CityStateMarkerOptions cityStateOptions, String color) {
+ super(cityStateOptions);
+ infoWindowBackgroundColor = color;
+ }
- public String getInfoWindowBackgroundColor() {
- return infoWindowBackgroundColor;
- }
+ public String getInfoWindowBackgroundColor() {
+ return infoWindowBackgroundColor;
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarkerOptions.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarkerOptions.java
index a4c32da92c..874c644af7 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarkerOptions.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarkerOptions.java
@@ -11,58 +11,58 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
public class CityStateMarkerOptions extends BaseMarkerOptions<CityStateMarker, CityStateMarkerOptions> {
- private String infoWindowBackgroundColor;
+ private String infoWindowBackgroundColor;
- public CityStateMarkerOptions infoWindowBackground(String color) {
- infoWindowBackgroundColor = color;
- return getThis();
- }
+ public CityStateMarkerOptions infoWindowBackground(String color) {
+ infoWindowBackgroundColor = color;
+ return getThis();
+ }
- public CityStateMarkerOptions() {
- }
+ public CityStateMarkerOptions() {
+ }
- private CityStateMarkerOptions(Parcel in) {
- position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
- snippet(in.readString());
- String iconId = in.readString();
- Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
- Icon icon = IconFactory.recreate(iconId, iconBitmap);
- icon(icon);
- title(in.readString());
- }
+ private CityStateMarkerOptions(Parcel in) {
+ position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
+ snippet(in.readString());
+ String iconId = in.readString();
+ Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
+ Icon icon = IconFactory.recreate(iconId, iconBitmap);
+ icon(icon);
+ title(in.readString());
+ }
- @Override
- public CityStateMarkerOptions getThis() {
- return this;
- }
+ @Override
+ public CityStateMarkerOptions getThis() {
+ return this;
+ }
- @Override
- public CityStateMarker getMarker() {
- return new CityStateMarker(this, infoWindowBackgroundColor);
- }
+ @Override
+ public CityStateMarker getMarker() {
+ return new CityStateMarker(this, infoWindowBackgroundColor);
+ }
- public static final Parcelable.Creator<CityStateMarkerOptions> CREATOR
- = new Parcelable.Creator<CityStateMarkerOptions>() {
- public CityStateMarkerOptions createFromParcel(Parcel in) {
- return new CityStateMarkerOptions(in);
- }
+ public static final Parcelable.Creator<CityStateMarkerOptions> CREATOR
+ = new Parcelable.Creator<CityStateMarkerOptions>() {
+ public CityStateMarkerOptions createFromParcel(Parcel in) {
+ return new CityStateMarkerOptions(in);
+ }
- public CityStateMarkerOptions[] newArray(int size) {
- return new CityStateMarkerOptions[size];
- }
+ public CityStateMarkerOptions[] newArray(int size) {
+ return new CityStateMarkerOptions[size];
+ }
};
- @Override
- public int describeContents() {
- return 0;
- }
+ @Override
+ public int describeContents() {
+ return 0;
+ }
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(position, flags);
- out.writeString(snippet);
- out.writeString(icon.getId());
- out.writeParcelable(icon.getBitmap(), flags);
- out.writeString(title);
- }
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(position, flags);
+ out.writeString(snippet);
+ out.writeString(icon.getId());
+ out.writeParcelable(icon.getBitmap(), flags);
+ out.writeString(title);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarker.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarker.java
index 7503b48df3..af97c9df69 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarker.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarker.java
@@ -5,20 +5,20 @@ import com.mapbox.mapboxsdk.annotations.Marker;
public class CountryMarker extends Marker {
- private String abbrevName;
- private int flagRes;
+ private String abbrevName;
+ private int flagRes;
- public CountryMarker(BaseMarkerOptions baseMarkerOptions, String abbrevName, int iconRes) {
- super(baseMarkerOptions);
- this.abbrevName = abbrevName;
- this.flagRes = iconRes;
- }
+ public CountryMarker(BaseMarkerOptions baseMarkerOptions, String abbrevName, int iconRes) {
+ super(baseMarkerOptions);
+ this.abbrevName = abbrevName;
+ this.flagRes = iconRes;
+ }
- public String getAbbrevName() {
- return abbrevName;
- }
+ public String getAbbrevName() {
+ return abbrevName;
+ }
- public int getFlagRes() {
- return flagRes;
- }
+ public int getFlagRes() {
+ return flagRes;
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerOptions.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerOptions.java
index ac1ff25bf2..0a64359979 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerOptions.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerOptions.java
@@ -11,65 +11,65 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
public class CountryMarkerOptions extends BaseMarkerOptions<CountryMarker, CountryMarkerOptions> {
- private String abbrevName;
- private int flagRes;
+ private String abbrevName;
+ private int flagRes;
- public CountryMarkerOptions abbrevName(String name) {
- abbrevName = name;
- return getThis();
- }
+ public CountryMarkerOptions abbrevName(String name) {
+ abbrevName = name;
+ return getThis();
+ }
- public CountryMarkerOptions flagRes(int imageRes) {
- flagRes = imageRes;
- return getThis();
- }
+ public CountryMarkerOptions flagRes(int imageRes) {
+ flagRes = imageRes;
+ return getThis();
+ }
- public CountryMarkerOptions() {
- }
+ public CountryMarkerOptions() {
+ }
- private CountryMarkerOptions(Parcel in) {
- position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
- snippet(in.readString());
- String iconId = in.readString();
- Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
- Icon icon = IconFactory.recreate(iconId, iconBitmap);
- icon(icon);
- title(in.readString());
- }
+ private CountryMarkerOptions(Parcel in) {
+ position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
+ snippet(in.readString());
+ String iconId = in.readString();
+ Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
+ Icon icon = IconFactory.recreate(iconId, iconBitmap);
+ icon(icon);
+ title(in.readString());
+ }
- @Override
- public CountryMarkerOptions getThis() {
- return this;
- }
+ @Override
+ public CountryMarkerOptions getThis() {
+ return this;
+ }
- @Override
- public CountryMarker getMarker() {
- return new CountryMarker(this, abbrevName, flagRes);
- }
+ @Override
+ public CountryMarker getMarker() {
+ return new CountryMarker(this, abbrevName, flagRes);
+ }
- public static final Parcelable.Creator<CountryMarkerOptions> CREATOR
- = new Parcelable.Creator<CountryMarkerOptions>() {
- public CountryMarkerOptions createFromParcel(Parcel in) {
- return new CountryMarkerOptions(in);
- }
+ public static final Parcelable.Creator<CountryMarkerOptions> CREATOR
+ = new Parcelable.Creator<CountryMarkerOptions>() {
+ public CountryMarkerOptions createFromParcel(Parcel in) {
+ return new CountryMarkerOptions(in);
+ }
- public CountryMarkerOptions[] newArray(int size) {
- return new CountryMarkerOptions[size];
- }
+ public CountryMarkerOptions[] newArray(int size) {
+ return new CountryMarkerOptions[size];
+ }
};
- @Override
- public int describeContents() {
- return 0;
- }
+ @Override
+ public int describeContents() {
+ return 0;
+ }
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(position, flags);
- out.writeString(snippet);
- out.writeString(icon.getId());
- out.writeParcelable(icon.getBitmap(), flags);
- out.writeString(title);
- }
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(position, flags);
+ out.writeString(snippet);
+ out.writeString(icon.getId());
+ out.writeParcelable(icon.getBitmap(), flags);
+ out.writeString(title);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerView.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerView.java
index 64f0565026..cab03e4f7a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerView.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerView.java
@@ -5,20 +5,20 @@ import com.mapbox.mapboxsdk.annotations.MarkerView;
public class CountryMarkerView extends MarkerView {
- private String abbrevName;
- private int flagRes;
+ private String abbrevName;
+ private int flagRes;
- public CountryMarkerView(BaseMarkerViewOptions baseMarkerViewOptions, String abbrevName, int flagRes) {
- super(baseMarkerViewOptions);
- this.abbrevName = abbrevName;
- this.flagRes = flagRes;
- }
+ public CountryMarkerView(BaseMarkerViewOptions baseMarkerViewOptions, String abbrevName, int flagRes) {
+ super(baseMarkerViewOptions);
+ this.abbrevName = abbrevName;
+ this.flagRes = flagRes;
+ }
- public String getAbbrevName() {
- return abbrevName;
- }
+ public String getAbbrevName() {
+ return abbrevName;
+ }
- public int getFlagRes() {
- return flagRes;
- }
+ public int getFlagRes() {
+ return flagRes;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java
index 9059b5978b..4dc9195ffd 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java
@@ -11,91 +11,89 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
public class CountryMarkerViewOptions extends BaseMarkerViewOptions<CountryMarkerView, CountryMarkerViewOptions> {
- private String abbrevName;
- private int flagRes;
-
- public CountryMarkerViewOptions() {
- }
-
- protected CountryMarkerViewOptions(Parcel in) {
- position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
- snippet(in.readString());
- title(in.readString());
- flat(in.readByte() != 0);
- anchor(in.readFloat(), in.readFloat());
- infoWindowAnchor(in.readFloat(), in.readFloat());
- rotation(in.readFloat());
- visible(in.readByte() != 0);
- alpha(in.readFloat());
- if (in.readByte() != 0) {
- // this means we have an icon
- String iconId = in.readString();
- Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
- Icon icon = IconFactory.recreate(iconId, iconBitmap);
- icon(icon);
- }
- abbrevName(in.readString());
- flagRes(in.readInt());
- }
-
- @Override
- public CountryMarkerViewOptions getThis() {
- return this;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(getPosition(), flags);
- out.writeString(getSnippet());
- out.writeString(getTitle());
- out.writeByte((byte) (isFlat() ? 1 : 0));
- out.writeFloat(getAnchorU());
- out.writeFloat(getAnchorV());
- out.writeFloat(getInfoWindowAnchorU());
- out.writeFloat(getInfoWindowAnchorV());
- out.writeFloat(getRotation());
- out.writeByte((byte) (isVisible() ? 1 : 0));
- out.writeFloat(getAlpha());
- Icon icon = getIcon();
- out.writeByte((byte) (icon != null ? 1 : 0));
- if (icon != null) {
- out.writeString(getIcon().getId());
- out.writeParcelable(getIcon().getBitmap(), flags);
- }
- out.writeString(abbrevName);
- out.writeInt(flagRes);
+ private String abbrevName;
+ private int flagRes;
+
+ public CountryMarkerViewOptions() {
+ }
+
+ protected CountryMarkerViewOptions(Parcel in) {
+ position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
+ snippet(in.readString());
+ title(in.readString());
+ flat(in.readByte() != 0);
+ anchor(in.readFloat(), in.readFloat());
+ infoWindowAnchor(in.readFloat(), in.readFloat());
+ rotation(in.readFloat());
+ visible(in.readByte() != 0);
+ alpha(in.readFloat());
+ if (in.readByte() != 0) {
+ // this means we have an icon
+ String iconId = in.readString();
+ Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
+ Icon icon = IconFactory.recreate(iconId, iconBitmap);
+ icon(icon);
}
-
- @Override
- public CountryMarkerView getMarker() {
- return new CountryMarkerView(this, abbrevName, flagRes);
- }
-
- public CountryMarkerViewOptions abbrevName(String abbrevName) {
- this.abbrevName = abbrevName;
- return getThis();
- }
-
- public CountryMarkerViewOptions flagRes(int flagRes) {
- this.flagRes = flagRes;
- return getThis();
+ abbrevName(in.readString());
+ flagRes(in.readInt());
+ }
+
+ @Override
+ public CountryMarkerViewOptions getThis() {
+ return this;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(getPosition(), flags);
+ out.writeString(getSnippet());
+ out.writeString(getTitle());
+ out.writeByte((byte) (isFlat() ? 1 : 0));
+ out.writeFloat(getAnchorU());
+ out.writeFloat(getAnchorV());
+ out.writeFloat(getInfoWindowAnchorU());
+ out.writeFloat(getInfoWindowAnchorV());
+ out.writeFloat(getRotation());
+ out.writeByte((byte) (isVisible() ? 1 : 0));
+ out.writeFloat(getAlpha());
+ Icon icon = getIcon();
+ out.writeByte((byte) (icon != null ? 1 : 0));
+ if (icon != null) {
+ out.writeString(getIcon().getId());
+ out.writeParcelable(getIcon().getBitmap(), flags);
}
-
- public static final Parcelable.Creator<CountryMarkerViewOptions> CREATOR
- = new Parcelable.Creator<CountryMarkerViewOptions>() {
- public CountryMarkerViewOptions createFromParcel(Parcel in) {
- return new CountryMarkerViewOptions(in);
- }
-
- public CountryMarkerViewOptions[] newArray(int size) {
- return new CountryMarkerViewOptions[size];
- }
+ out.writeString(abbrevName);
+ out.writeInt(flagRes);
+ }
+
+ @Override
+ public CountryMarkerView getMarker() {
+ return new CountryMarkerView(this, abbrevName, flagRes);
+ }
+
+ public CountryMarkerViewOptions abbrevName(String abbrevName) {
+ this.abbrevName = abbrevName;
+ return getThis();
+ }
+
+ public CountryMarkerViewOptions flagRes(int flagRes) {
+ this.flagRes = flagRes;
+ return getThis();
+ }
+
+ public static final Parcelable.Creator<CountryMarkerViewOptions> CREATOR
+ = new Parcelable.Creator<CountryMarkerViewOptions>() {
+ public CountryMarkerViewOptions createFromParcel(Parcel in) {
+ return new CountryMarkerViewOptions(in);
+ }
+
+ public CountryMarkerViewOptions[] newArray(int size) {
+ return new CountryMarkerViewOptions[size];
+ }
};
-
-
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/PulseMarkerView.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/PulseMarkerView.java
index 48867ea5eb..971c3359b2 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/PulseMarkerView.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/PulseMarkerView.java
@@ -5,7 +5,7 @@ import com.mapbox.mapboxsdk.annotations.MarkerView;
public class PulseMarkerView extends MarkerView {
- public PulseMarkerView(BaseMarkerViewOptions baseMarkerViewOptions) {
- super(baseMarkerViewOptions);
- }
+ public PulseMarkerView(BaseMarkerViewOptions baseMarkerViewOptions) {
+ super(baseMarkerViewOptions);
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/PulseMarkerViewOptions.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/PulseMarkerViewOptions.java
index 70ff6a22e2..20c479fc9b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/PulseMarkerViewOptions.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/PulseMarkerViewOptions.java
@@ -11,69 +11,69 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
public class PulseMarkerViewOptions extends BaseMarkerViewOptions<PulseMarkerView, PulseMarkerViewOptions> {
- public PulseMarkerViewOptions() {
- }
+ public PulseMarkerViewOptions() {
+ }
- protected PulseMarkerViewOptions(Parcel in) {
- position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
- snippet(in.readString());
- title(in.readString());
- flat(in.readByte() != 0);
- anchor(in.readFloat(), in.readFloat());
- selected = in.readByte() != 0;
- rotation(in.readFloat());
- if (in.readByte() != 0) {
- // this means we have an icon
- String iconId = in.readString();
- Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
- Icon icon = IconFactory.recreate(iconId, iconBitmap);
- icon(icon);
- }
+ protected PulseMarkerViewOptions(Parcel in) {
+ position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
+ snippet(in.readString());
+ title(in.readString());
+ flat(in.readByte() != 0);
+ anchor(in.readFloat(), in.readFloat());
+ selected = in.readByte() != 0;
+ rotation(in.readFloat());
+ if (in.readByte() != 0) {
+ // this means we have an icon
+ String iconId = in.readString();
+ Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
+ Icon icon = IconFactory.recreate(iconId, iconBitmap);
+ icon(icon);
}
+ }
- @Override
- public PulseMarkerViewOptions getThis() {
- return this;
- }
+ @Override
+ public PulseMarkerViewOptions getThis() {
+ return this;
+ }
- @Override
- public int describeContents() {
- return 0;
- }
+ @Override
+ public int describeContents() {
+ return 0;
+ }
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(getPosition(), flags);
- out.writeString(getSnippet());
- out.writeString(getTitle());
- out.writeByte((byte) (isFlat() ? 1 : 0));
- out.writeFloat(getAnchorU());
- out.writeFloat(getAnchorV());
- out.writeFloat(getInfoWindowAnchorU());
- out.writeFloat(getInfoWindowAnchorV());
- out.writeByte((byte) (selected ? 1 : 0));
- out.writeFloat(getRotation());
- Icon icon = getIcon();
- out.writeByte((byte) (icon != null ? 1 : 0));
- if (icon != null) {
- out.writeString(getIcon().getId());
- out.writeParcelable(getIcon().getBitmap(), flags);
- }
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(getPosition(), flags);
+ out.writeString(getSnippet());
+ out.writeString(getTitle());
+ out.writeByte((byte) (isFlat() ? 1 : 0));
+ out.writeFloat(getAnchorU());
+ out.writeFloat(getAnchorV());
+ out.writeFloat(getInfoWindowAnchorU());
+ out.writeFloat(getInfoWindowAnchorV());
+ out.writeByte((byte) (selected ? 1 : 0));
+ out.writeFloat(getRotation());
+ Icon icon = getIcon();
+ out.writeByte((byte) (icon != null ? 1 : 0));
+ if (icon != null) {
+ out.writeString(getIcon().getId());
+ out.writeParcelable(getIcon().getBitmap(), flags);
}
+ }
- @Override
- public PulseMarkerView getMarker() {
- return new PulseMarkerView(this);
- }
+ @Override
+ public PulseMarkerView getMarker() {
+ return new PulseMarkerView(this);
+ }
- public static final Parcelable.Creator<CountryMarkerViewOptions> CREATOR
- = new Parcelable.Creator<CountryMarkerViewOptions>() {
- public CountryMarkerViewOptions createFromParcel(Parcel in) {
- return new CountryMarkerViewOptions(in);
- }
+ public static final Parcelable.Creator<CountryMarkerViewOptions> CREATOR
+ = new Parcelable.Creator<CountryMarkerViewOptions>() {
+ public CountryMarkerViewOptions createFromParcel(Parcel in) {
+ return new CountryMarkerViewOptions(in);
+ }
- public CountryMarkerViewOptions[] newArray(int size) {
- return new CountryMarkerViewOptions[size];
- }
+ public CountryMarkerViewOptions[] newArray(int size) {
+ return new CountryMarkerViewOptions[size];
+ }
};
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerView.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerView.java
index c0a589cb57..f507c5f1ab 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerView.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerView.java
@@ -5,14 +5,14 @@ import com.mapbox.mapboxsdk.annotations.MarkerView;
public class TextMarkerView extends MarkerView {
- private String text;
+ private String text;
- public TextMarkerView(BaseMarkerViewOptions baseMarkerViewOptions, String text) {
- super(baseMarkerViewOptions);
- this.text = text;
- }
+ public TextMarkerView(BaseMarkerViewOptions baseMarkerViewOptions, String text) {
+ super(baseMarkerViewOptions);
+ this.text = text;
+ }
- public String getText() {
- return text;
- }
+ public String getText() {
+ return text;
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerViewOptions.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerViewOptions.java
index a91ec5e541..df7c575f74 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerViewOptions.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerViewOptions.java
@@ -11,81 +11,81 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
public class TextMarkerViewOptions extends BaseMarkerViewOptions<TextMarkerView, TextMarkerViewOptions> {
- private String text;
+ private String text;
- public TextMarkerViewOptions() {
- }
+ public TextMarkerViewOptions() {
+ }
- protected TextMarkerViewOptions(Parcel in) {
- position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
- snippet(in.readString());
- title(in.readString());
- flat(in.readByte() != 0);
- anchor(in.readFloat(), in.readFloat());
- infoWindowAnchor(in.readFloat(), in.readFloat());
- rotation(in.readFloat());
- visible(in.readByte() != 0);
- alpha(in.readFloat());
- if (in.readByte() != 0) {
- // this means we have an icon
- String iconId = in.readString();
- Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
- Icon icon = IconFactory.recreate(iconId, iconBitmap);
- icon(icon);
- }
- text(in.readString());
+ protected TextMarkerViewOptions(Parcel in) {
+ position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
+ snippet(in.readString());
+ title(in.readString());
+ flat(in.readByte() != 0);
+ anchor(in.readFloat(), in.readFloat());
+ infoWindowAnchor(in.readFloat(), in.readFloat());
+ rotation(in.readFloat());
+ visible(in.readByte() != 0);
+ alpha(in.readFloat());
+ if (in.readByte() != 0) {
+ // this means we have an icon
+ String iconId = in.readString();
+ Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
+ Icon icon = IconFactory.recreate(iconId, iconBitmap);
+ icon(icon);
}
+ text(in.readString());
+ }
- @Override
- public TextMarkerViewOptions getThis() {
- return this;
- }
+ @Override
+ public TextMarkerViewOptions getThis() {
+ return this;
+ }
- @Override
- public int describeContents() {
- return 0;
- }
+ @Override
+ public int describeContents() {
+ return 0;
+ }
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(getPosition(), flags);
- out.writeString(getSnippet());
- out.writeString(getTitle());
- out.writeByte((byte) (isFlat() ? 1 : 0));
- out.writeFloat(getAnchorU());
- out.writeFloat(getAnchorV());
- out.writeFloat(getInfoWindowAnchorU());
- out.writeFloat(getInfoWindowAnchorV());
- out.writeFloat(getRotation());
- out.writeByte((byte) (isVisible() ? 1 : 0));
- out.writeFloat(alpha);
- Icon icon = getIcon();
- out.writeByte((byte) (icon != null ? 1 : 0));
- if (icon != null) {
- out.writeString(getIcon().getId());
- out.writeParcelable(getIcon().getBitmap(), flags);
- }
- out.writeString(text);
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(getPosition(), flags);
+ out.writeString(getSnippet());
+ out.writeString(getTitle());
+ out.writeByte((byte) (isFlat() ? 1 : 0));
+ out.writeFloat(getAnchorU());
+ out.writeFloat(getAnchorV());
+ out.writeFloat(getInfoWindowAnchorU());
+ out.writeFloat(getInfoWindowAnchorV());
+ out.writeFloat(getRotation());
+ out.writeByte((byte) (isVisible() ? 1 : 0));
+ out.writeFloat(alpha);
+ Icon icon = getIcon();
+ out.writeByte((byte) (icon != null ? 1 : 0));
+ if (icon != null) {
+ out.writeString(getIcon().getId());
+ out.writeParcelable(getIcon().getBitmap(), flags);
}
+ out.writeString(text);
+ }
- @Override
- public TextMarkerView getMarker() {
- return new TextMarkerView(this, text);
- }
+ @Override
+ public TextMarkerView getMarker() {
+ return new TextMarkerView(this, text);
+ }
- public TextMarkerViewOptions text(String text) {
- this.text = text;
- return getThis();
- }
+ public TextMarkerViewOptions text(String text) {
+ this.text = text;
+ return getThis();
+ }
- public static final Parcelable.Creator<CountryMarkerViewOptions> CREATOR
- = new Parcelable.Creator<CountryMarkerViewOptions>() {
- public CountryMarkerViewOptions createFromParcel(Parcel in) {
- return new CountryMarkerViewOptions(in);
- }
+ public static final Parcelable.Creator<CountryMarkerViewOptions> CREATOR
+ = new Parcelable.Creator<CountryMarkerViewOptions>() {
+ public CountryMarkerViewOptions createFromParcel(Parcel in) {
+ return new CountryMarkerViewOptions(in);
+ }
- public CountryMarkerViewOptions[] newArray(int size) {
- return new CountryMarkerViewOptions[size];
- }
+ public CountryMarkerViewOptions[] newArray(int size) {
+ return new CountryMarkerViewOptions[size];
+ }
};
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/constants/AppConstant.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/constants/AppConstant.java
index 095e47a3d2..aaef7f8a51 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/constants/AppConstant.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/constants/AppConstant.java
@@ -2,5 +2,5 @@ package com.mapbox.mapboxsdk.testapp.model.constants;
public class AppConstant {
- public static final int STYLE_VERSION = 9;
+ public static final int STYLE_VERSION = 9;
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer.java
index 2901060459..8c049d7730 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer.java
@@ -1,12 +1,15 @@
package com.mapbox.mapboxsdk.testapp.model.customlayer;
public class ExampleCustomLayer {
- static {
- System.loadLibrary("example-custom-layer");
- }
-
- public native static long createContext();
- public static long InitializeFunction;
- public static long RenderFunction;
- public static long DeinitializeFunction;
+ static {
+ System.loadLibrary("example-custom-layer");
+ }
+
+ public static native long createContext();
+
+ public static native void setColor(float red, float green, float blue, float alpha);
+
+ public static long InitializeFunction;
+ public static long RenderFunction;
+ public static long DeinitializeFunction;
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java
index 493153d1c1..b70144123f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java
@@ -7,51 +7,51 @@ import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
-import android.util.Log;
+
+import timber.log.Timber;
+
import android.widget.EditText;
import com.mapbox.mapboxsdk.testapp.R;
public class OfflineDownloadRegionDialog extends DialogFragment {
- private static final String LOG_TAG = "OfflineDownloadRegionDialog";
-
- public interface DownloadRegionDialogListener {
- void onDownloadRegionDialogPositiveClick(String regionName);
- }
-
- DownloadRegionDialogListener listener;
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- listener = (DownloadRegionDialogListener) activity;
- }
-
- @NonNull
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-
- // Let the user choose a name for the region
- final EditText regionNameEdit = new EditText(getActivity());
-
- builder.setTitle("Choose a name for the region")
- .setIcon(R.drawable.ic_airplanemode_active_black_24dp)
- .setView(regionNameEdit)
- .setPositiveButton("Start", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- String regionName = regionNameEdit.getText().toString();
- listener.onDownloadRegionDialogPositiveClick(regionName);
- }
- }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Log.d(LOG_TAG, "Download cancelled.");
- }
- });
-
- return builder.create();
- }
+ public interface DownloadRegionDialogListener {
+ void onDownloadRegionDialogPositiveClick(String regionName);
+ }
+
+ DownloadRegionDialogListener listener;
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ listener = (DownloadRegionDialogListener) activity;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+
+ // Let the user choose a name for the region
+ final EditText regionNameEdit = new EditText(getActivity());
+
+ builder.setTitle("Choose a name for the region")
+ .setIcon(R.drawable.ic_airplanemode_active_black_24dp)
+ .setView(regionNameEdit)
+ .setPositiveButton("Start", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String regionName = regionNameEdit.getText().toString();
+ listener.onDownloadRegionDialogPositiveClick(regionName);
+ }
+ }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Timber.d("Download cancelled.");
+ }
+ });
+
+ return builder.create();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java
index 2a5de869a5..65c4102a8c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java
@@ -6,7 +6,8 @@ import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
-import android.util.Log;
+
+import timber.log.Timber;
import com.mapbox.mapboxsdk.testapp.R;
@@ -14,35 +15,33 @@ import java.util.ArrayList;
public class OfflineListRegionsDialog extends DialogFragment {
- private static final String LOG_TAG = "OfflineListRegionsDialog";
-
- public static final String ITEMS = "ITEMS";
-
- @NonNull
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-
- // Read args
- Bundle args = getArguments();
- ArrayList<String> offlineRegionsNames = (args == null ? null : args.getStringArrayList(ITEMS));
- CharSequence[] items = offlineRegionsNames.toArray(new CharSequence[offlineRegionsNames.size()]);
-
- builder.setTitle("List of offline regions")
- .setIcon(R.drawable.ic_airplanemode_active_black_24dp)
- .setItems(items, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Log.d(LOG_TAG, "Selected item: " + which);
- }
- })
- .setPositiveButton("Accept", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Log.d(LOG_TAG, "Dialog dismissed");
- }
- });
-
- return builder.create();
- }
+ public static final String ITEMS = "ITEMS";
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+
+ // Read args
+ Bundle args = getArguments();
+ ArrayList<String> offlineRegionsNames = (args == null ? null : args.getStringArrayList(ITEMS));
+ CharSequence[] items = offlineRegionsNames.toArray(new CharSequence[offlineRegionsNames.size()]);
+
+ builder.setTitle("List of offline regions")
+ .setIcon(R.drawable.ic_airplanemode_active_black_24dp)
+ .setItems(items, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Timber.d("Selected item: " + which);
+ }
+ })
+ .setPositiveButton("Accept", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Timber.d("Dialog dismissed");
+ }
+ });
+
+ return builder.create();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java
index 97bfb90d41..e2271bd5ff 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java
@@ -2,26 +2,25 @@ package com.mapbox.mapboxsdk.testapp.utils;
import android.content.Context;
import android.graphics.Typeface;
-import android.util.Log;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import timber.log.Timber;
import java.util.Hashtable;
public class FontCache {
- private static Hashtable<String, Typeface> fontCache = new Hashtable<>();
+ private static Hashtable<String, Typeface> fontCache = new Hashtable<>();
- public static Typeface get(String name, Context context) {
- Typeface tf = fontCache.get(name);
- if (tf == null) {
- try {
- tf = Typeface.createFromAsset(context.getAssets(), name);
- fontCache.put(name, tf);
- } catch (Exception exception) {
- Log.e(MapboxConstants.TAG, "Font not found");
- }
- }
- return tf;
+ public static Typeface get(String name, Context context) {
+ Typeface tf = fontCache.get(name);
+ if (tf == null) {
+ try {
+ tf = Typeface.createFromAsset(context.getAssets(), name);
+ fontCache.put(name, tf);
+ } catch (Exception exception) {
+ Timber.e("Font not found");
+ }
}
+ return tf;
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java
index d6a8280c6a..0d21fd2c71 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java
@@ -20,54 +20,54 @@ import java.util.List;
public class GeoParseUtil {
- public static String loadStringFromAssets(final Context context, final String fileName) throws IOException {
- if (TextUtils.isEmpty(fileName)) {
- throw new NullPointerException("No GeoJSON File Name passed in.");
- }
- InputStream is = context.getAssets().open(fileName);
- BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
- return readAll(rd);
+ public static String loadStringFromAssets(final Context context, final String fileName) throws IOException {
+ if (TextUtils.isEmpty(fileName)) {
+ throw new NullPointerException("No GeoJSON File Name passed in.");
}
+ InputStream is = context.getAssets().open(fileName);
+ BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
+ return readAll(rd);
+ }
- public static List<LatLng> parseGeoJSONCoordinates(String geojsonStr) throws JSONException {
- List<LatLng> latLngs = new ArrayList<>();
- JSONObject jsonObject = new JSONObject(geojsonStr);
- JSONArray features = jsonObject.getJSONArray("features");
- int featureLength = features.length();
- for (int j = 0; j < featureLength; ++j) {
- JSONObject feature = features.getJSONObject(j);
- JSONObject geometry = feature.getJSONObject("geometry");
- String type = geometry.getString("type");
- JSONArray coordinates;
- if (type.equals("Polygon")) {
- coordinates = geometry.getJSONArray("coordinates").getJSONArray(0);
- } else {
- coordinates = geometry.getJSONArray("coordinates");
- }
- int len = coordinates.length();
- for (int i = 0; i < len; ++i) {
- if (coordinates.get(i) instanceof JSONArray) {
- JSONArray coord = coordinates.getJSONArray(i);
- double lng = coord.getDouble(0);
- double lat = coord.getDouble(1);
- latLngs.add(new LatLng(lat, lng));
- } else {
- double lng = coordinates.getDouble(0);
- double lat = coordinates.getDouble(1);
- latLngs.add(new LatLng(lat, lng));
- break;
- }
- }
+ public static List<LatLng> parseGeoJsonCoordinates(String geojsonStr) throws JSONException {
+ List<LatLng> latLngs = new ArrayList<>();
+ JSONObject jsonObject = new JSONObject(geojsonStr);
+ JSONArray features = jsonObject.getJSONArray("features");
+ int featureLength = features.length();
+ for (int j = 0; j < featureLength; ++j) {
+ JSONObject feature = features.getJSONObject(j);
+ JSONObject geometry = feature.getJSONObject("geometry");
+ String type = geometry.getString("type");
+ JSONArray coordinates;
+ if (type.equals("Polygon")) {
+ coordinates = geometry.getJSONArray("coordinates").getJSONArray(0);
+ } else {
+ coordinates = geometry.getJSONArray("coordinates");
+ }
+ int len = coordinates.length();
+ for (int i = 0; i < len; ++i) {
+ if (coordinates.get(i) instanceof JSONArray) {
+ JSONArray coord = coordinates.getJSONArray(i);
+ double lng = coord.getDouble(0);
+ double lat = coord.getDouble(1);
+ latLngs.add(new LatLng(lat, lng));
+ } else {
+ double lng = coordinates.getDouble(0);
+ double lat = coordinates.getDouble(1);
+ latLngs.add(new LatLng(lat, lng));
+ break;
}
- return latLngs;
+ }
}
+ return latLngs;
+ }
- private static String readAll(Reader rd) throws IOException {
- StringBuilder sb = new StringBuilder();
- int cp;
- while ((cp = rd.read()) != -1) {
- sb.append((char) cp);
- }
- return sb.toString();
+ private static String readAll(Reader rd) throws IOException {
+ StringBuilder sb = new StringBuilder();
+ int cp;
+ while ((cp = rd.read()) != -1) {
+ sb.append((char) cp);
}
+ return sb.toString();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ItemClickSupport.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ItemClickSupport.java
index ba74d1d837..414a781544 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ItemClickSupport.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ItemClickSupport.java
@@ -6,90 +6,90 @@ import android.view.View;
import com.mapbox.mapboxsdk.testapp.R;
public class ItemClickSupport {
- private final RecyclerView recyclerView;
- private OnItemClickListener onItemClickListener;
- private OnItemLongClickListener onItemLongClickListener;
- private View.OnClickListener onClickListener = new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (onItemClickListener != null) {
- RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(view);
- onItemClickListener.onItemClicked(recyclerView, holder.getAdapterPosition(), view);
- }
+ private final RecyclerView recyclerView;
+ private OnItemClickListener onItemClickListener;
+ private OnItemLongClickListener onItemLongClickListener;
+ private View.OnClickListener onClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (onItemClickListener != null) {
+ RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(view);
+ onItemClickListener.onItemClicked(recyclerView, holder.getAdapterPosition(), view);
+ }
+ }
+ };
+ private View.OnLongClickListener onLongClickListener = new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View view) {
+ if (onItemLongClickListener != null) {
+ RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(view);
+ return onItemLongClickListener.onItemLongClicked(recyclerView, holder.getAdapterPosition(), view);
+ }
+ return false;
+ }
+ };
+ private RecyclerView.OnChildAttachStateChangeListener attachListener
+ = new RecyclerView.OnChildAttachStateChangeListener() {
+ @Override
+ public void onChildViewAttachedToWindow(View view) {
+ if (onItemClickListener != null) {
+ view.setOnClickListener(onClickListener);
}
- };
- private View.OnLongClickListener onLongClickListener = new View.OnLongClickListener() {
- @Override
- public boolean onLongClick(View view) {
- if (onItemLongClickListener != null) {
- RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(view);
- return onItemLongClickListener.onItemLongClicked(recyclerView, holder.getAdapterPosition(), view);
- }
- return false;
- }
- };
- private RecyclerView.OnChildAttachStateChangeListener attachListener
- = new RecyclerView.OnChildAttachStateChangeListener() {
- @Override
- public void onChildViewAttachedToWindow(View view) {
- if (onItemClickListener != null) {
- view.setOnClickListener(onClickListener);
- }
- if (onItemLongClickListener != null) {
- view.setOnLongClickListener(onLongClickListener);
- }
+ if (onItemLongClickListener != null) {
+ view.setOnLongClickListener(onLongClickListener);
}
+ }
- @Override
- public void onChildViewDetachedFromWindow(View view) {
+ @Override
+ public void onChildViewDetachedFromWindow(View view) {
- }
+ }
};
- private ItemClickSupport(RecyclerView recyclerView) {
- this.recyclerView = recyclerView;
- this.recyclerView.setTag(R.id.item_click_support, this);
- this.recyclerView.addOnChildAttachStateChangeListener(attachListener);
- }
+ private ItemClickSupport(RecyclerView recyclerView) {
+ this.recyclerView = recyclerView;
+ this.recyclerView.setTag(R.id.item_click_support, this);
+ this.recyclerView.addOnChildAttachStateChangeListener(attachListener);
+ }
- public static ItemClickSupport addTo(RecyclerView view) {
- ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
- if (support == null) {
- support = new ItemClickSupport(view);
- }
- return support;
+ public static ItemClickSupport addTo(RecyclerView view) {
+ ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
+ if (support == null) {
+ support = new ItemClickSupport(view);
}
+ return support;
+ }
- public static ItemClickSupport removeFrom(RecyclerView view) {
- ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
- if (support != null) {
- support.detach(view);
- }
- return support;
+ public static ItemClickSupport removeFrom(RecyclerView view) {
+ ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
+ if (support != null) {
+ support.detach(view);
}
+ return support;
+ }
- public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
- onItemClickListener = listener;
- return this;
- }
+ public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
+ onItemClickListener = listener;
+ return this;
+ }
- public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
- onItemLongClickListener = listener;
- return this;
- }
+ public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
+ onItemLongClickListener = listener;
+ return this;
+ }
- private void detach(RecyclerView view) {
- view.removeOnChildAttachStateChangeListener(attachListener);
- view.setTag(R.id.item_click_support, null);
- }
+ private void detach(RecyclerView view) {
+ view.removeOnChildAttachStateChangeListener(attachListener);
+ view.setTag(R.id.item_click_support, null);
+ }
- public interface OnItemClickListener {
+ public interface OnItemClickListener {
- void onItemClicked(RecyclerView recyclerView, int position, View view);
- }
+ void onItemClicked(RecyclerView recyclerView, int position, View view);
+ }
- public interface OnItemLongClickListener {
+ public interface OnItemLongClickListener {
- boolean onItemLongClicked(RecyclerView recyclerView, int position, View view);
- }
+ boolean onItemLongClicked(RecyclerView recyclerView, int position, View view);
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java
index ee4ae039ee..8c6ab3e211 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java
@@ -1,7 +1,8 @@
package com.mapbox.mapboxsdk.testapp.utils;
import android.support.annotation.NonNull;
-import android.util.Log;
+
+import timber.log.Timber;
import org.json.JSONObject;
@@ -10,27 +11,27 @@ import static com.mapbox.mapboxsdk.testapp.activity.offline.OfflineActivity.JSON
public class OfflineUtils {
- public static String convertRegionName(@NonNull byte[] metadata) {
- try {
- String json = new String(metadata, JSON_CHARSET);
- JSONObject jsonObject = new JSONObject(json);
- return jsonObject.getString(JSON_FIELD_REGION_NAME);
- } catch (Exception exception) {
- return null;
- }
+ public static String convertRegionName(@NonNull byte[] metadata) {
+ try {
+ String json = new String(metadata, JSON_CHARSET);
+ JSONObject jsonObject = new JSONObject(json);
+ return jsonObject.getString(JSON_FIELD_REGION_NAME);
+ } catch (Exception exception) {
+ return null;
}
+ }
- public static byte[] convertRegionName(String regionName) {
- byte[] metadata = null;
- try {
- JSONObject jsonObject = new JSONObject();
- jsonObject.put(JSON_FIELD_REGION_NAME, regionName);
- String json = jsonObject.toString();
- metadata = json.getBytes(JSON_CHARSET);
- } catch (Exception exception) {
- Log.e("OfflineUtils", "Failed to encode metadata: " + exception.getMessage());
- }
- return metadata;
+ public static byte[] convertRegionName(String regionName) {
+ byte[] metadata = null;
+ try {
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put(JSON_FIELD_REGION_NAME, regionName);
+ String json = jsonObject.toString();
+ metadata = json.getBytes(JSON_CHARSET);
+ } catch (Exception exception) {
+ Timber.e("Failed to encode metadata: " + exception.getMessage());
}
-
+ return metadata;
+ }
+
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimingLogger.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimingLogger.java
index 544e737780..e096aa202d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimingLogger.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimingLogger.java
@@ -1,3 +1,4 @@
+package com.mapbox.mapboxsdk.testapp.utils;
/*
* Copyright (C) 2007 The Android Open Source Project
*
@@ -13,17 +14,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.mapbox.mapboxsdk.testapp.utils;
+
+import android.os.SystemClock;
import java.util.ArrayList;
-import android.os.SystemClock;
-import android.util.Log;
+import timber.log.Timber;
/**
* A utility class to help log timings splits throughout a method call.
* Typical usage is:
- *
+ * <p>
* <pre>
* TimingLogger timings = new TimingLogger(TAG, "methodA");
* // ... do some work A ...
@@ -34,9 +35,9 @@ import android.util.Log;
* timings.addSplit("work C");
* timings.dumpToLog();
* </pre>
- *
+ * <p>
* <p>The dumpToLog call would add the following to the log:</p>
- *
+ * <p>
* <pre>
* D/TAG ( 3459): methodA: begin
* D/TAG ( 3459): methodA: 9 ms, work A
@@ -46,108 +47,114 @@ import android.util.Log;
* </pre>
*/
public class TimingLogger {
- /**
- * The Log tag to use for checking Log.isLoggable and for
- * logging the timings.
- */
- private String mTag;
- /**
- * A label to be included in every log.
- */
- private String mLabel;
- /**
- * Used to track whether Log.isLoggable was enabled at reset time.
- */
- private boolean mDisabled;
- /**
- * Stores the time of each split.
- */
- ArrayList<Long> mSplits;
- /**
- * Stores the labels for each split.
- */
- ArrayList<String> mSplitLabels;
+ /**
+ * The Log tag to use for checking Log.isLoggable and for
+ * logging the timings.
+ */
+ private String tag;
+ /**
+ * A label to be included in every log.
+ */
+ private String label;
+ /**
+ * Used to track whether Log.isLoggable was enabled at reset time.
+ */
+ private boolean disabled;
+ /**
+ * Stores the time of each split.
+ */
+ private ArrayList<Long> splits;
+ /**
+ * Stores the labels for each split.
+ */
+ private ArrayList<String> splitLabels;
- /**
- * Create and initialize a TimingLogger object that will log using
- * the specific tag. If the Log.isLoggable is not enabled to at
- * least the Log.VERBOSE level for that tag at creation time then
- * the addSplit and dumpToLog call will do nothing.
- *
- * @param tag the log tag to use while logging the timings
- * @param label a string to be displayed with each log
- */
- public TimingLogger(String tag, String label) {
- reset(tag, label);
- }
+ /**
+ * Create and initialize a TimingLogger object that will log using
+ * the specific tag. If the Log.isLoggable is not enabled to at
+ * least the Log.VERBOSE level for that tag at creation time then
+ * the addSplit and dumpToLog call will do nothing.
+ *
+ * @param tag the log tag to use while logging the timings
+ * @param label a string to be displayed with each log
+ */
+ public TimingLogger(String tag, String label) {
+ reset(tag, label);
+ }
- /**
- * Clear and initialize a TimingLogger object that will log using
- * the specific tag. If the Log.isLoggable is not enabled to at
- * least the Log.VERBOSE level for that tag at creation time then
- * the addSplit and dumpToLog call will do nothing.
- *
- * @param tag the log tag to use while logging the timings
- * @param label a string to be displayed with each log
- */
- public void reset(String tag, String label) {
- mTag = tag;
- mLabel = label;
- reset();
- }
+ /**
+ * Clear and initialize a TimingLogger object that will log using
+ * the specific tag. If the Log.isLoggable is not enabled to at
+ * least the Log.VERBOSE level for that tag at creation time then
+ * the addSplit and dumpToLog call will do nothing.
+ *
+ * @param tag the log tag to use while logging the timings
+ * @param label a string to be displayed with each log
+ */
+ public void reset(String tag, String label) {
+ this.tag = tag;
+ this.label = label;
+ reset();
+ }
- /**
- * Clear and initialize a TimingLogger object that will log using
- * the tag and label that was specified previously, either via
- * the constructor or a call to reset(tag, label). If the
- * Log.isLoggable is not enabled to at least the Log.VERBOSE
- * level for that tag at creation time then the addSplit and
- * dumpToLog call will do nothing.
- */
- public void reset() {
- mDisabled = false; //!Log.isLoggable(mTag, Log.VERBOSE);
- if (mDisabled) return;
- if (mSplits == null) {
- mSplits = new ArrayList<Long>();
- mSplitLabels = new ArrayList<String>();
- } else {
- mSplits.clear();
- mSplitLabels.clear();
- }
- addSplit(null);
+ /**
+ * Clear and initialize a TimingLogger object that will log using
+ * the tag and label that was specified previously, either via
+ * the constructor or a call to reset(tag, label). If the
+ * Log.isLoggable is not enabled to at least the Log.VERBOSE
+ * level for that tag at creation time then the addSplit and
+ * dumpToLog call will do nothing.
+ */
+ public void reset() {
+ disabled = false; //!Log.isLoggable(tag, Log.VERBOSE);
+ if (disabled) {
+ return;
+ }
+ if (splits == null) {
+ splits = new ArrayList<Long>();
+ splitLabels = new ArrayList<String>();
+ } else {
+ splits.clear();
+ splitLabels.clear();
}
+ addSplit(null);
+ }
- /**
- * Add a split for the current time, labeled with splitLabel. If
- * Log.isLoggable was not enabled to at least the Log.VERBOSE for
- * the specified tag at construction or reset() time then this
- * call does nothing.
- *
- * @param splitLabel a label to associate with this split.
- */
- public void addSplit(String splitLabel) {
- if (mDisabled) return;
- long now = SystemClock.elapsedRealtime();
- mSplits.add(now);
- mSplitLabels.add(splitLabel);
+ /**
+ * Add a split for the current time, labeled with splitLabel. If
+ * Log.isLoggable was not enabled to at least the Log.VERBOSE for
+ * the specified tag at construction or reset() time then this
+ * call does nothing.
+ *
+ * @param splitLabel a label to associate with this split.
+ */
+ public void addSplit(String splitLabel) {
+ if (disabled) {
+ return;
}
+ long now = SystemClock.elapsedRealtime();
+ splits.add(now);
+ splitLabels.add(splitLabel);
+ }
- /**
- * Dumps the timings to the log using Log.d(). If Log.isLoggable was
- * not enabled to at least the Log.VERBOSE for the specified tag at
- * construction or reset() time then this call does nothing.
- */
- public void dumpToLog() {
- if (mDisabled) return;
- Log.d(mTag, mLabel + ": begin");
- final long first = mSplits.get(0);
- long now = first;
- for (int i = 1; i < mSplits.size(); i++) {
- now = mSplits.get(i);
- final String splitLabel = mSplitLabels.get(i);
- final long prev = mSplits.get(i - 1);
- Log.d(mTag, mLabel + ": " + (now - prev) + " ms, " + splitLabel);
- }
- Log.d(mTag, mLabel + ": end, " + (now - first) + " ms");
+ /**
+ * Dumps the timings to the log using Timber.d(). If Log.isLoggable was
+ * not enabled to at least the Log.VERBOSE for the specified tag at
+ * construction or reset() time then this call does nothing.
+ */
+ public void dumpToLog() {
+ if (disabled) {
+ return;
+ }
+ Timber.d(label + ": begin");
+ final long first = splits.get(0);
+ long now = first;
+ for (int i = 1; i < splits.size(); i++) {
+ now = splits.get(i);
+ final String splitLabel = splitLabels.get(i);
+ final long prev = splits.get(i - 1);
+ Timber.d(label + ": " + (now - prev) + " ms, " + splitLabel);
}
+ Timber.d(label + ": end, " + (now - first) + " ms");
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ToolbarComposer.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ToolbarComposer.java
index 7822e41bd9..3fa3bcd26f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ToolbarComposer.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ToolbarComposer.java
@@ -15,35 +15,35 @@ import com.mapbox.mapboxsdk.testapp.R;
public class ToolbarComposer {
- /**
- * Initialises an up navigation toolbar with id R.id.toolbar on an AppCompatActivity.
- *
- * @param activity The activity hosting the Toolbar with id R.id.toolbar
- */
- @Nullable
- public static Toolbar initDefaultUpToolbar(@NonNull AppCompatActivity activity) {
- return initDefaultUpToolbar(activity, R.id.toolbar);
- }
-
- /**
- * Initialises an up navigation toolbar given a view id on an AppCompatActivity.
- *
- * @param activity The activity hosting the Toolbar
- * @param toolbarRes The view id resource used to look up the Toolbar
- */
- @Nullable
- public static Toolbar initDefaultUpToolbar(@NonNull AppCompatActivity activity, @IdRes int toolbarRes) {
- Toolbar toolbar = (Toolbar) activity.findViewById(toolbarRes);
- if (toolbar != null) {
- activity.setSupportActionBar(toolbar);
-
- ActionBar actionBar = activity.getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
- }
- return toolbar;
+ /**
+ * Initialises an up navigation toolbar with id R.id.toolbar on an AppCompatActivity.
+ *
+ * @param activity The activity hosting the Toolbar with id R.id.toolbar
+ */
+ @Nullable
+ public static Toolbar initDefaultUpToolbar(@NonNull AppCompatActivity activity) {
+ return initDefaultUpToolbar(activity, R.id.toolbar);
+ }
+
+ /**
+ * Initialises an up navigation toolbar given a view id on an AppCompatActivity.
+ *
+ * @param activity The activity hosting the Toolbar
+ * @param toolbarRes The view id resource used to look up the Toolbar
+ */
+ @Nullable
+ public static Toolbar initDefaultUpToolbar(@NonNull AppCompatActivity activity, @IdRes int toolbarRes) {
+ Toolbar toolbar = (Toolbar) activity.findViewById(toolbarRes);
+ if (toolbar != null) {
+ activity.setSupportActionBar(toolbar);
+
+ ActionBar actionBar = activity.getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
}
+ return toolbar;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-hdpi/ic_launcher_round.png b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..b5e1edc785
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-hdpi/ic_launcher_round.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-mdpi/ic_launcher_round.png b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..0b28b92c61
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-mdpi/ic_launcher_round.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xhdpi/ic_launcher_round.png b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..eeddbaca3f
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xhdpi/ic_launcher_round.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/ic_launcher_round.png b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..bbc99eae41
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/ic_launcher_round.png b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..70ab174fc2
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_directions_bus_black_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_directions_bus_black_24dp.xml
new file mode 100644
index 0000000000..e16e259792
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_directions_bus_black_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M4,16c0,0.88 0.39,1.67 1,2.22L5,20c0,0.55 0.45,1 1,1h1c0.55,0 1,-0.45 1,-1v-1h8v1c0,0.55 0.45,1 1,1h1c0.55,0 1,-0.45 1,-1v-1.78c0.61,-0.55 1,-1.34 1,-2.22L20,6c0,-3.5 -3.58,-4 -8,-4s-8,0.5 -8,4v10zM7.5,17c-0.83,0 -1.5,-0.67 -1.5,-1.5S6.67,14 7.5,14s1.5,0.67 1.5,1.5S8.33,17 7.5,17zM16.5,17c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM18,11L6,11L6,6h12v5z"/>
+</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_add_sprite.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_add_sprite.xml
index 086b18fea1..e0e2cbfdab 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_add_sprite.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_add_sprite.xml
@@ -16,10 +16,10 @@
android:id="@id/mapView"
android:layout_below="@id/toolbar"
android:layout_width="match_parent"
- app:center_latitude="52.519003"
- app:center_longitude="13.400972"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="16"
+ app:mapbox_cameraTargetLat="52.519003"
+ app:mapbox_cameraTargetLng="13.400972"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="16"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animated_marker.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animated_marker.xml
index eabfc30b25..6534c23c72 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animated_marker.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animated_marker.xml
@@ -17,9 +17,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/toolbar"
- app:center_latitude="51.502615"
- app:center_longitude="4.972326"
- app:style_url="@string/style_light"
- app:zoom="6" />
+ app:mapbox_cameraTargetLat="51.502615"
+ app:mapbox_cameraTargetLng="4.972326"
+ app:mapbox_styleUrl="@string/mapbox_style_light"
+ app:mapbox_cameraZoom="6" />
</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animation_types.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animation_types.xml
index 5a5fb5f604..8a139083f8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animation_types.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animation_types.xml
@@ -17,9 +17,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/toolbar"
- app:center_latitude="51.50325"
- app:center_longitude="-0.11968"
- app:zoom="15" />
+ app:mapbox_cameraTargetLat="51.50325"
+ app:mapbox_cameraTargetLng="-0.11968"
+ app:mapbox_cameraZoom="15" />
<LinearLayout
android:layout_width="match_parent"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_position.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_position.xml
index 2e08f79e95..a1d7a8351d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_position.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_position.xml
@@ -21,7 +21,7 @@
android:id="@id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:style_url="@string/style_mapbox_streets" />
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_test.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_test.xml
new file mode 100644
index 0000000000..4f86120097
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_test.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <!-- TODO remove zoom #6747-->
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_below="@id/toolbar"
+ app:mapbox_cameraZoom="1" />
+
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_car_driving.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_car_driving.xml
index c61055ee4e..f52d5e70c2 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_car_driving.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_car_driving.xml
@@ -16,9 +16,9 @@
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:my_location_foreground_tint="@color/primary"
- app:my_location_accuracy_tint="@color/primary"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="15" />
+ app:mapbox_myLocationTintColor="@color/primary"
+ app:mapbox_myLocationAccuracyTintColor="@color/primary"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="15" />
</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_circle_layer.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_circle_layer.xml
new file mode 100644
index 0000000000..4aecf36c71
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_circle_layer.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_below="@id/toolbar"
+ app:mapbox_cameraTargetLat="1.350057"
+ app:mapbox_cameraTargetLng="103.849218"
+ app:mapbox_styleUrl="@string/mapbox_style_dark"
+ app:mapbox_cameraZoom="10"/>
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@id/fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_margin="@dimen/fab_margin"
+ android:src="@drawable/ic_directions_bus_black_24dp"
+ app:backgroundTint="@android:color/white" />
+
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_circlelayer.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_circlelayer.xml
index 086b18fea1..e0e2cbfdab 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_circlelayer.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_circlelayer.xml
@@ -16,10 +16,10 @@
android:id="@id/mapView"
android:layout_below="@id/toolbar"
android:layout_width="match_parent"
- app:center_latitude="52.519003"
- app:center_longitude="13.400972"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="16"
+ app:mapbox_cameraTargetLat="52.519003"
+ app:mapbox_cameraTargetLng="13.400972"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="16"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_directions.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_directions.xml
index 5de3651272..bc100b6059 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_directions.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_directions.xml
@@ -16,6 +16,6 @@
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:style_url="@string/style_mapbox_streets" />
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets" />
</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_dynamic_marker.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_dynamic_marker.xml
index d6507559ec..2625e65bbf 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_dynamic_marker.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_dynamic_marker.xml
@@ -26,12 +26,12 @@
android:id="@id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:center_latitude="51.506675"
- app:center_longitude="-0.128699"
- app:compass_fade_facing_north="false"
- app:direction="90"
- app:tilt="40"
- app:zoom="10" />
+ app:mapbox_cameraTargetLat="51.506675"
+ app:mapbox_cameraTargetLng="-0.128699"
+ app:mapbox_uiCompassFadeFacingNorth="false"
+ app:mapbox_cameraBearing="90"
+ app:mapbox_cameraTilt="40"
+ app:mapbox_cameraZoom="10" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_geocoder.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_geocoder.xml
index 002ece58bf..d13d16a73e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_geocoder.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_geocoder.xml
@@ -17,9 +17,9 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="5"
- app:center_latitude="38.90962"
- app:center_longitude="-77.04341"
- app:zoom="15" />
+ app:mapbox_cameraTargetLat="38.90962"
+ app:mapbox_cameraTargetLng="-77.04341"
+ app:mapbox_cameraZoom="15" />
<TextView
android:id="@+id/message"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow.xml
index e69983941a..1c8e33fb33 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow.xml
@@ -16,9 +16,9 @@
android:id="@id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:center_latitude="38.897705003219784"
- app:center_longitude="-77.03655168667463"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="15" />
+ app:mapbox_cameraTargetLat="38.897705003219784"
+ app:mapbox_cameraTargetLng="-77.03655168667463"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="15" />
</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow_adapter.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow_adapter.xml
index dde63c8420..134c3f331e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow_adapter.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow_adapter.xml
@@ -16,9 +16,9 @@
android:id="@id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:center_latitude="47.798202"
- app:center_longitude="7.573781"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="4" />
+ app:mapbox_cameraTargetLat="47.798202"
+ app:mapbox_cameraTargetLng="7.573781"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="4" />
</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow_adapter_dynamic.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow_adapter_dynamic.xml
index dde63c8420..134c3f331e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow_adapter_dynamic.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_infowindow_adapter_dynamic.xml
@@ -16,9 +16,9 @@
android:id="@id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:center_latitude="47.798202"
- app:center_longitude="7.573781"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="4" />
+ app:mapbox_cameraTargetLat="47.798202"
+ app:mapbox_cameraTargetLng="7.573781"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="4" />
</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_source.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_source.xml
new file mode 100644
index 0000000000..a1d7a8351d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_source.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <android.support.design.widget.CoordinatorLayout
+ android:id="@+id/coordinator_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets" />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end|bottom"
+ android:layout_margin="@dimen/fab_margin"
+ android:src="@drawable/ic_input_24dp"
+ app:backgroundTint="@android:color/white" />
+
+ </android.support.design.widget.CoordinatorLayout>
+</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml
index c1f09a36d0..3732326f39 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml
@@ -14,10 +14,10 @@
<com.mapbox.mapboxsdk.maps.MapView
android:id="@id/mapView"
- app:center_latitude="50.871062"
- app:center_longitude="1.583210"
- app:direction="220"
- app:zoom="10"
+ app:mapbox_cameraTargetLat="50.871062"
+ app:mapbox_cameraTargetLng="1.583210"
+ app:mapbox_cameraBearing="220"
+ app:mapbox_cameraZoom="10"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/toolbar" />
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_simple.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_simple.xml
new file mode 100644
index 0000000000..4ad49e4a9f
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_simple.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_bulk.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_bulk.xml
index 90cb1a90b3..229d8e87c1 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_bulk.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_bulk.xml
@@ -22,11 +22,11 @@
android:id="@id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:center_latitude="38.87031"
+ app:mapbox_cameraTargetLat="38.87031"
android:layout_below="@id/toolbar"
- app:center_longitude="-77.00897"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="10" />
+ app:mapbox_cameraTargetLng="-77.00897"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="10" />
<TextView
android:id="@+id/countView"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view.xml
index 5d285958f1..f06975466b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view.xml
@@ -16,10 +16,10 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"
- app:center_latitude="38.907192"
- app:center_longitude="-77.036871"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="12" />
+ app:mapbox_cameraTargetLat="38.907192"
+ app:mapbox_cameraTargetLng="-77.036871"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="12" />
<TextView
android:id="@+id/countView"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_in_rect.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_in_rect.xml
new file mode 100644
index 0000000000..36dd89c885
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_in_rect.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@+id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_below="@id/toolbar"/>
+
+ <FrameLayout
+ android:id="@+id/selection_box"
+ android:layout_width="150dp"
+ android:layout_height="150dp"
+ android:layout_centerInParent="true"
+ android:alpha="0.3"
+ android:background="#1d72da"/>
+
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_scale.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_scale.xml
index c59f41539c..8f98b5bea2 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_scale.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_scale.xml
@@ -39,6 +39,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title"
+ android:clickable="false"
android:layout_marginLeft="56dp"
android:progress="0" />
@@ -52,9 +53,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"
- app:center_latitude="38.907192"
- app:center_longitude="-77.036871"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="12" />
+ app:mapbox_cameraTargetLat="38.907192"
+ app:mapbox_cameraTargetLng="-77.036871"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="12" />
</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_maxmin_zoom.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_maxmin_zoom.xml
index 951344e35a..20de7c00bf 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_maxmin_zoom.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_maxmin_zoom.xml
@@ -17,9 +17,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/toolbar"
- app:center_latitude="-1.063510"
- app:center_longitude=" 32.895425"
- app:style_url="@string/style_satellite_streets"
- app:zoom="4" />
+ app:mapbox_cameraTargetLat="-1.063510"
+ app:mapbox_cameraTargetLng=" 32.895425"
+ app:mapbox_styleUrl="@string/mapbox_style_satellite_streets"
+ app:mapbox_cameraZoom="4" />
</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_dot_color.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_dot_color.xml
index af755c72a1..d41cc79326 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_dot_color.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_dot_color.xml
@@ -1,50 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:mapbox="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
+ android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/primary"
- android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<com.mapbox.mapboxsdk.maps.MapView
android:id="@id/mapView"
- android:layout_below="@+id/toolbar"
android:layout_width="match_parent"
- android:layout_height="match_parent"/>
+ android:layout_height="match_parent"
+ android:layout_below="@+id/toolbar"
+ mapbox:mapbox_uiAttribution="false"
+ mapbox:mapbox_uiLogo="false"/>
<LinearLayout
+ style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
+ android:background="@color/accent"
android:orientation="horizontal"
- android:weightSum="3">
+ android:weightSum="4">
<Button
android:id="@+id/default_user_dot_coloring_button"
+ style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:text="@string/button_user_dot_default" />
+ android:text="@string/button_user_dot_default"
+ android:textColor="@color/white"/>
<Button
android:id="@+id/tint_user_dot_button"
+ style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:text="@string/button_user_dot_tint" />
+ android:text="@string/button_user_dot_tint"
+ android:textColor="@color/white"/>
<Button
android:id="@+id/user_accuracy_ring_tint_button"
+ style="?android:attr/buttonBarButtonStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/button_user_accuracy_ring_tint"
+ android:textColor="@color/white"/>
+
+ <Button
+ android:id="@+id/user_dot_transparent_button"
+ style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:text="@string/button_user_accuracy_ring_tint" />
+ android:text="@string/button_user_transparent_tint"
+ android:textColor="@color/white"/>
- </LinearLayout>
+ </LinearLayout>
</RelativeLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_tracking.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_tracking.xml
index 19c30dbb8d..95f084506b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_tracking.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_tracking.xml
@@ -42,9 +42,9 @@
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:my_location_foreground_tint="@color/primary"
- app:my_location_accuracy_tint="@color/primary"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="15" />
+ app:mapbox_myLocationTintColor="@color/primary"
+ app:mapbox_myLocationAccuracyTintColor="@color/primary"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="15" />
</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polyline.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polyline.xml
index 9e2f875192..d856676260 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polyline.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polyline.xml
@@ -17,11 +17,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/toolbar"
- app:attribution_tint="@android:color/holo_green_dark"
- app:center_latitude="47.798202"
- app:center_longitude="7.573781"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="4" />
+ app:mapbox_uiAttributionTintColor="@android:color/holo_green_dark"
+ app:mapbox_cameraTargetLat="47.798202"
+ app:mapbox_cameraTargetLng="7.573781"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="4" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml
index 9ff79686d2..f5a9a17917 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml
@@ -17,12 +17,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/toolbar"
- app:attribution_gravity="top|end"
- app:center_latitude="45.1855569"
- app:center_longitude="5.7215506"
- app:logo_gravity="top|end"
- app:logo_margin_right="10dp"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="11" />
+ app:mapbox_uiAttributionGravity="top|end"
+ app:mapbox_cameraTargetLat="45.1855569"
+ app:mapbox_cameraTargetLng="5.7215506"
+ app:mapbox_uiLogoGravity="top|end"
+ app:mapbox_uiLogoMarginRight="10dp"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="11" />
</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_features_box.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_features_box.xml
index e1d710880c..dfd067cec7 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_features_box.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_features_box.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -14,7 +15,10 @@
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_below="@id/toolbar" />
+ android:layout_below="@id/toolbar"
+ app:mapbox_cameraTargetLat="52.0907"
+ app:mapbox_cameraTargetLng="5.1214"
+ app:mapbox_cameraZoom="16" />
<FrameLayout
android:id="@+id/selection_box"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_features_point.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_features_point.xml
index 4c0d067c14..6889a5fac1 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_features_point.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_features_point.xml
@@ -1,19 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/primary"
- android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<com.mapbox.mapboxsdk.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_below="@id/toolbar"/>
+ android:layout_below="@id/toolbar"
+ app:mapbox_cameraTargetLat="52.0907"
+ app:mapbox_cameraTargetLng="5.1214"
+ app:mapbox_cameraZoom="16" />
</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_scroll_by.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_scroll_by.xml
index c5bb8d71b3..5e80a0e1b6 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_scroll_by.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_scroll_by.xml
@@ -80,10 +80,10 @@
android:id="@id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:center_latitude="37.176546"
- app:center_longitude="-3.599007"
- app:style_url="@string/style_emerald"
- app:zoom="15" />
+ app:mapbox_cameraTargetLat="37.176546"
+ app:mapbox_cameraTargetLng="-3.599007"
+ app:mapbox_styleUrl="@string/mapbox_style_emerald"
+ app:mapbox_cameraZoom="15" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_style_file.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_style_file.xml
index 086b18fea1..e0e2cbfdab 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_style_file.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_style_file.xml
@@ -16,10 +16,10 @@
android:id="@id/mapView"
android:layout_below="@id/toolbar"
android:layout_width="match_parent"
- app:center_latitude="52.519003"
- app:center_longitude="13.400972"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="16"
+ app:mapbox_cameraTargetLat="52.519003"
+ app:mapbox_cameraTargetLng="13.400972"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
+ app:mapbox_cameraZoom="16"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_surfaceview_mediacontrols.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_surfaceview_mediacontrols.xml
index 8fa94041ff..364e86adda 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_surfaceview_mediacontrols.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_surfaceview_mediacontrols.xml
@@ -17,7 +17,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/toolbar"
- app:style_url="@string/style_light" />
+ app:mapbox_styleUrl="@string/mapbox_style_light" />
<FrameLayout
android:id="@+id/container"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_symbollayer.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_symbollayer.xml
new file mode 100644
index 0000000000..67892abbd1
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_symbollayer.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_below="@id/toolbar"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"/>
+
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_video_view.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_video_view.xml
index 979b30d2b4..b640f9f878 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_video_view.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_video_view.xml
@@ -27,11 +27,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"
- mapbox:attribution_gravity="top"
- mapbox:center_latitude="34.4021"
- mapbox:center_longitude="-119.7081"
- mapbox:logo_gravity="top"
- mapbox:style_url="mapbox://styles/mapbox/streets-v9"
- mapbox:zoom="13" />
+ mapbox:mapbox_uiAttributionGravity="top"
+ mapbox:mapbox_cameraTargetLat="34.4021"
+ mapbox:mapbox_cameraTargetLng="-119.7081"
+ mapbox:mapbox_uiLogoGravity="top"
+ mapbox:mapbox_styleUrl="mapbox://styles/mapbox/streets-v9"
+ mapbox:mapbox_cameraZoom="13" />
</RelativeLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_dialog_map.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_dialog_map.xml
index 51ec3c4677..b40ad1273d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_dialog_map.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_dialog_map.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -10,9 +9,10 @@
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- mapbox:center_latitude="47.6077"
- mapbox:center_longitude="-122.3421"
- mapbox:style_url="mapbox://styles/mapbox/streets-v9"
- mapbox:zoom="11"/>
+ mapbox:mapbox_cameraTargetLat="47.6077"
+ mapbox:mapbox_cameraTargetLng="-122.3421"
+ mapbox:mapbox_cameraZoom="11"
+ mapbox:mapbox_renderTextureMode="true"
+ mapbox:mapbox_styleUrl="mapbox://styles/mapbox/streets-v9" />
</LinearLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_custom_layer.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_custom_layer.xml
index 43465cce62..ec1f756333 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_custom_layer.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_custom_layer.xml
@@ -5,4 +5,13 @@
<item
android:id="@+id/action_update_layer"
android:title="Update layer (invalidate)" />
+ <item
+ android:id="@+id/action_set_color_red"
+ android:title="Red" />
+ <item
+ android:id="@+id/action_set_color_green"
+ android:title="Green" />
+ <item
+ android:id="@+id/action_set_color_blue"
+ android:title="Blue" />
</menu> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_symbol_layer.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_symbol_layer.xml
new file mode 100644
index 0000000000..e6fd1fce45
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_symbol_layer.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/action_toggle_text_size"
+ android:title="Toggle text size"/>
+
+ <item
+ android:id="@+id/action_toggle_text_field"
+ android:title="Toggle text field contents"/>
+
+ <item
+ android:id="@+id/action_toggle_text_font"
+ android:title="Toggle text font"/>
+
+</menu> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/raw/test_points_utrecht.geojson b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/raw/test_points_utrecht.geojson
new file mode 100644
index 0000000000..d7b8ede72f
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/raw/test_points_utrecht.geojson
@@ -0,0 +1,49 @@
+{
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 5.12100,
+ 52.09082
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 5.12160,
+ 52.09082
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 5.12160,
+ 52.09056
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 5.12100,
+ 52.09056
+ ]
+ }
+ }
+ ]
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
index a4f19f1e01..53688cdf35 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
@@ -58,19 +58,21 @@
<string name="activity_minmax_zoom">Min/Max Zoom</string>
<string name="activity_viewpager">ViewPager</string>
<string name="activity_runtime_style">Runtime Style</string>
+ <string name="activity_circle_layer">Circle layer</string>
<string name="activity_style_file">Local Style file</string>
<string name="activity_geojson_clustering">GeoJson Clustering</string>
<string name="activity_geojson_realtime">Add live realtime data</string>
<string name="activity_print">Print a map</string>
- <string name="activity_surfaceview_overlay">SurfaceView MediaOverlay</string>
<string name="activity_query_rendered_feature_properties">Query feature properties</string>
<string name="activity_query_rendered_features_box_count">Count features in box</string>
+ <string name="activity_query_rendered_features_box_symbol_count">Count symbols in box</string>
<string name="activity_query_rendered_features_box_highlight">Highlight features in box</string>
- <string name="activity_circle">Add Circle</string>
+ <string name="activity_symbol_layer">Symbols</string>
<string name="activity_add_sprite">Add Custom Sprite</string>
<string name="activity_navigation_drawer">Android SDK View integration</string>
- <string name="activity_video_view">Video View</string>
+ <string name="activity_simple_map">Simple Map</string>
<string name="activity_map_in_dialog">Dialog with map</string>
+ <string name="activity_marker_view_rectangle">Marker views in rectangle</string>
<!-- Description -->
<string name="description_user_location_tracking">Tracks the location of the user</string>
@@ -111,21 +113,23 @@
<string name="description_location_picker">Use a fixed Marker to select your location</string>
<string name="description_viewpager">Use SupportMapFragments in a ViewPager</string>
<string name="description_runtime_style">Adopt the map style on the fly</string>
- <string name="description_circle">Use GeoJson source to show a circle</string>
+ <string name="description_symbol_layer">Manipulate symbols at runtime</string>
<string name="description_custom_sprite">Use a custom sprite in a Symbol Layer</string>
<string name="description_geojson_clustering">Use GeoJson sources and dynamic layers to cluster information</string>
<string name="description_geojson_realtime">Use realtime GeoJSON data streams to move a symbol on your map</string>
<string name="description_print">Shows how to print a map</string>
<string name="description_navigation_drawer">Test animation of Android SDK View components</string>
- <string name="description_surfaceview_mediacontrols">Test overlaying SurfaceView</string>
<string name="description_query_rendered_feature_properties_point">Query rendered feature properties on click</string>
<string name="description_query_rendered_features_box_count">Count all rendered features in box</string>
+ <string name="description_query_rendered_features_box_symbol_count">Count all rendered symbols in box</string>
<string name="description_query_rendered_features_box_highlight">Hightligh buildings in box</string>
<string name="description_car_driving">MyLocationView follow map update example</string>
- <string name="description_video_view">Android video view on top of the map view</string>
+ <string name="description_simple_map">Shows a simple map</string>
<string name="description_add_remove_markers">Based on zoom level</string>
<string name="description_style_file">Use a local file as the style</string>
<string name="description_map_in_dialog">Display a map inside a dialog fragment</string>
+ <string name="description_marker_view_rectangle">Marker Views within a rectangle</string>
+ <string name="description_circle_layer">Show bus stops and route in Singapore</string>
<string name="menuitem_title_concurrent_infowindow">Concurrent Open InfoWindows</string>
<string name="menuitem_title_deselect_markers_on_tap">Deselect Markers On Tap</string>
@@ -165,6 +169,7 @@
<string name="button_user_dot_default">Default</string>
<string name="button_user_dot_tint">Tint dot</string>
<string name="button_user_accuracy_ring_tint">Tint ring</string>
+ <string name="button_user_transparent_tint">tran</string>
<string name="button_open_dialog">Open dialog</string>
<string name="label_fps">FPS:</string>
@@ -231,4 +236,4 @@
<string name="menuitem_title_rotate_gesture_enabled">Enable rotate gestures</string>
<string name="menuitem_title_scroll_gesture_enabled">Enable scroll gestures</string>
-</resources>
+</resources> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/AnnotationTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/AnnotationTest.java
index 76658c242f..611e4f978c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/AnnotationTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/AnnotationTest.java
@@ -17,75 +17,75 @@ import static org.mockito.Mockito.verify;
public class AnnotationTest {
- @InjectMocks
- private MapboxMap mapboxMap = mock(MapboxMap.class);
- private Annotation annotation;
- private Annotation compare = new Annotation() {
- @Override
- public long getId() {
- return 1;
- }
- };
-
- @Before
- public void beforeTest() {
- annotation = new Annotation() {
- // empty child
- };
+ @InjectMocks
+ private MapboxMap mapboxMap = mock(MapboxMap.class);
+ private Annotation annotation;
+ private Annotation compare = new Annotation() {
+ @Override
+ public long getId() {
+ return 1;
}
+ };
- @Test
- public void testSanity() {
- assertNotNull("markerOptions should not be null", annotation);
- }
+ @Before
+ public void beforeTest() {
+ annotation = new Annotation() {
+ // empty child
+ };
+ }
- @Test
- public void testRemove() {
- annotation.setId(1);
- annotation.setMapboxMap(mapboxMap);
- annotation.remove();
- verify(mapboxMap, times(1)).removeAnnotation(annotation);
- }
+ @Test
+ public void testSanity() {
+ assertNotNull("markerOptions should not be null", annotation);
+ }
- @Test
- public void testRemoveUnboundMapboxMap() {
- annotation.setId(1);
- annotation.remove();
- verify(mapboxMap, times(0)).removeAnnotation(annotation);
- }
+ @Test
+ public void testRemove() {
+ annotation.setId(1);
+ annotation.setMapboxMap(mapboxMap);
+ annotation.remove();
+ verify(mapboxMap, times(1)).removeAnnotation(annotation);
+ }
- @Test
- public void testCompareToEqual() {
- annotation.setId(1);
- assertEquals("conparable equal", 0, annotation.compareTo(compare));
- }
+ @Test
+ public void testRemoveUnboundMapboxMap() {
+ annotation.setId(1);
+ annotation.remove();
+ verify(mapboxMap, times(0)).removeAnnotation(annotation);
+ }
- @Test
- public void testCompareToHigher() {
- annotation.setId(3);
- assertEquals("conparable higher", -1, annotation.compareTo(compare));
- }
+ @Test
+ public void testCompareToEqual() {
+ annotation.setId(1);
+ assertEquals("conparable equal", 0, annotation.compareTo(compare));
+ }
- @Test
- public void testCompareTolower() {
- annotation.setId(0);
- assertEquals("conparable lower", 1, annotation.compareTo(compare));
- }
+ @Test
+ public void testCompareToHigher() {
+ annotation.setId(3);
+ assertEquals("conparable higher", -1, annotation.compareTo(compare));
+ }
- @Test
- public void testEquals() {
- Annotation holder = null;
- assertFalse(annotation.equals(holder));
- holder = annotation;
- assertTrue(annotation.equals(holder));
- assertFalse(annotation.equals(new Object()));
- }
+ @Test
+ public void testCompareTolower() {
+ annotation.setId(0);
+ assertEquals("conparable lower", 1, annotation.compareTo(compare));
+ }
- @Test
- public void testHashcode() {
- int id = 1;
- annotation.setId(id);
- assertSame("hashcode should match", annotation.hashCode(), id);
- }
+ @Test
+ public void testEquals() {
+ Annotation holder = null;
+ assertFalse(annotation.equals(holder));
+ holder = annotation;
+ assertTrue(annotation.equals(holder));
+ assertFalse(annotation.equals(new Object()));
+ }
+
+ @Test
+ public void testHashcode() {
+ int id = 1;
+ annotation.setId(id);
+ assertSame("hashcode should match", annotation.hashCode(), id);
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/IconTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/IconTest.java
index 9e95451cb1..5f6f6b6c6d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/IconTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/IconTest.java
@@ -12,44 +12,44 @@ import static junit.framework.Assert.assertNotSame;
public class IconTest {
- @Mock
- Bitmap mBitmap;
-
- @Before
- public void beforeTest() {
- MockitoAnnotations.initMocks(this);
- }
-
- @Test
- public void testId() {
- String id = "test";
- Icon icon = IconFactory.recreate(id, Bitmap.createBitmap(0, 0, Bitmap.Config.ALPHA_8));
- assertEquals("id should match", id, icon.getId());
- }
-
- @Test
- public void testBitmap() {
- Icon icon = IconFactory.recreate("test", mBitmap);
- assertEquals("bitmap should match", mBitmap, icon.getBitmap());
- }
-
- @Test
- public void testEquals() {
- Icon icon1 = IconFactory.recreate("test", mBitmap);
- Icon icon2 = IconFactory.recreate("test", mBitmap);
- assertEquals("icons should not match", icon1, icon2);
- }
-
- @Test
- public void testEqualsObject() {
- Icon icon = IconFactory.recreate("test", Bitmap.createBitmap(0, 0, Bitmap.Config.ALPHA_8));
- assertNotSame("icon should not match", new Object(), icon);
- }
-
- @Test
- public void testHashcode() {
- Icon icon = IconFactory.recreate("test", mBitmap);
- long expectedHashcode = 31 * mBitmap.hashCode() + "test".hashCode();
- assertEquals("hashcode should match", expectedHashcode, icon.hashCode());
- }
+ @Mock
+ Bitmap bitmap;
+
+ @Before
+ public void beforeTest() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testId() {
+ String id = "test";
+ Icon icon = IconFactory.recreate(id, Bitmap.createBitmap(0, 0, Bitmap.Config.ALPHA_8));
+ assertEquals("id should match", id, icon.getId());
+ }
+
+ @Test
+ public void testBitmap() {
+ Icon icon = IconFactory.recreate("test", bitmap);
+ assertEquals("bitmap should match", bitmap, icon.getBitmap());
+ }
+
+ @Test
+ public void testEquals() {
+ Icon icon1 = IconFactory.recreate("test", bitmap);
+ Icon icon2 = IconFactory.recreate("test", bitmap);
+ assertEquals("icons should not match", icon1, icon2);
+ }
+
+ @Test
+ public void testEqualsObject() {
+ Icon icon = IconFactory.recreate("test", Bitmap.createBitmap(0, 0, Bitmap.Config.ALPHA_8));
+ assertNotSame("icon should not match", new Object(), icon);
+ }
+
+ @Test
+ public void testHashcode() {
+ Icon icon = IconFactory.recreate("test", bitmap);
+ long expectedHashcode = 31 * bitmap.hashCode() + "test".hashCode();
+ assertEquals("hashcode should match", expectedHashcode, icon.hashCode());
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/InfoWindowTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/InfoWindowTest.java
index 1398f40009..94b629860e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/InfoWindowTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/InfoWindowTest.java
@@ -17,70 +17,70 @@ import static org.mockito.Mockito.when;
public class InfoWindowTest {
- @InjectMocks
- MapView mMapView = mock(MapView.class);
-
- @InjectMocks
- MapboxMap mMapboxMap = mock(MapboxMap.class);
-
- @Test
- public void testSanity() {
- InfoWindow infoWindow = new InfoWindow(mMapView, mMapboxMap);
- assertNotNull("infoWindow should exist", infoWindow);
- }
-
- @Test
- public void testBoundMarker() {
- MarkerOptions markerOptions = new MarkerOptions();
- Marker marker = markerOptions.position(new LatLng()).getMarker();
- InfoWindow infoWindow = new InfoWindow(mMapView, mMapboxMap).setBoundMarker(marker);
- assertEquals("marker should match", marker, infoWindow.getBoundMarker());
- }
-
- @Test
- public void testClose() {
- InfoWindow infoWindow = new InfoWindow(mMapView, mMapboxMap);
- infoWindow.close();
- assertEquals("infowindow should not be visible", false, infoWindow.isVisible());
- }
-
-
- @Test
- public void testOpen() {
- LatLng latLng = new LatLng(0, 0);
- Projection projection = mock(Projection.class);
- when(mMapboxMap.getProjection()).thenReturn(projection);
- when(projection.toScreenLocation(latLng)).thenReturn(new PointF(0, 0));
-
- InfoWindow infoWindow = new InfoWindow(mMapView, mMapboxMap);
- infoWindow.open(mMapView, new MarkerOptions().position(new LatLng()).getMarker(), latLng, 0, 0);
- assertEquals("infowindow should not be visible", true, infoWindow.isVisible());
- }
-
- @Test
- public void testOpenClose() {
- LatLng latLng = new LatLng(0, 0);
- Projection projection = mock(Projection.class);
- when(mMapboxMap.getProjection()).thenReturn(projection);
- when(projection.toScreenLocation(latLng)).thenReturn(new PointF(0, 0));
-
- InfoWindow infoWindow = new InfoWindow(mMapView, mMapboxMap);
- infoWindow.open(mMapView, new MarkerOptions().position(new LatLng()).getMarker(), latLng, 0, 0);
- infoWindow.close();
- assertEquals("infowindow should not be visible", false, infoWindow.isVisible());
- }
-
-
- @Test
- public void testUpdate() {
- LatLng latLng = new LatLng(0, 0);
- Projection projection = mock(Projection.class);
- when(mMapboxMap.getProjection()).thenReturn(projection);
- when(projection.toScreenLocation(latLng)).thenReturn(new PointF(0, 0));
-
- InfoWindow infoWindow = new InfoWindow(mMapView, mMapboxMap);
- infoWindow.open(mMapView, new MarkerOptions().position(latLng).getMarker(), latLng, 0, 0);
- infoWindow.update();
- }
+ @InjectMocks
+ MapView mMapView = mock(MapView.class);
+
+ @InjectMocks
+ MapboxMap mMapboxMap = mock(MapboxMap.class);
+
+ @Test
+ public void testSanity() {
+ InfoWindow infoWindow = new InfoWindow(mMapView, mMapboxMap);
+ assertNotNull("infoWindow should exist", infoWindow);
+ }
+
+ @Test
+ public void testBoundMarker() {
+ MarkerOptions markerOptions = new MarkerOptions();
+ Marker marker = markerOptions.position(new LatLng()).getMarker();
+ InfoWindow infoWindow = new InfoWindow(mMapView, mMapboxMap).setBoundMarker(marker);
+ assertEquals("marker should match", marker, infoWindow.getBoundMarker());
+ }
+
+ @Test
+ public void testClose() {
+ InfoWindow infoWindow = new InfoWindow(mMapView, mMapboxMap);
+ infoWindow.close();
+ assertEquals("infowindow should not be visible", false, infoWindow.isVisible());
+ }
+
+
+ @Test
+ public void testOpen() {
+ LatLng latLng = new LatLng(0, 0);
+ Projection projection = mock(Projection.class);
+ when(mMapboxMap.getProjection()).thenReturn(projection);
+ when(projection.toScreenLocation(latLng)).thenReturn(new PointF(0, 0));
+
+ InfoWindow infoWindow = new InfoWindow(mMapView, mMapboxMap);
+ infoWindow.open(mMapView, new MarkerOptions().position(new LatLng()).getMarker(), latLng, 0, 0);
+ assertEquals("infowindow should not be visible", true, infoWindow.isVisible());
+ }
+
+ @Test
+ public void testOpenClose() {
+ LatLng latLng = new LatLng(0, 0);
+ Projection projection = mock(Projection.class);
+ when(mMapboxMap.getProjection()).thenReturn(projection);
+ when(projection.toScreenLocation(latLng)).thenReturn(new PointF(0, 0));
+
+ InfoWindow infoWindow = new InfoWindow(mMapView, mMapboxMap);
+ infoWindow.open(mMapView, new MarkerOptions().position(new LatLng()).getMarker(), latLng, 0, 0);
+ infoWindow.close();
+ assertEquals("infowindow should not be visible", false, infoWindow.isVisible());
+ }
+
+
+ @Test
+ public void testUpdate() {
+ LatLng latLng = new LatLng(0, 0);
+ Projection projection = mock(Projection.class);
+ when(mMapboxMap.getProjection()).thenReturn(projection);
+ when(projection.toScreenLocation(latLng)).thenReturn(new PointF(0, 0));
+
+ InfoWindow infoWindow = new InfoWindow(mMapView, mMapboxMap);
+ infoWindow.open(mMapView, new MarkerOptions().position(latLng).getMarker(), latLng, 0, 0);
+ infoWindow.update();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java
index c4c294fb98..fa571e06b1 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java
@@ -16,145 +16,145 @@ import static org.mockito.Mockito.mock;
public class MarkerTest {
- @Test
- public void testSanity() {
- MarkerOptions markerOptions = new MarkerOptions();
- assertNotNull("markerOptions should not be null", markerOptions);
- }
-
- @Test
- public void testMarker() {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- assertNotNull("marker should not be null", markerOptions.getMarker());
- }
-
- @Test(expected = InvalidMarkerPositionException.class)
- public void testInvalidMarker(){
- new MarkerOptions().getMarker();
- }
-
- @Test
- public void testPosition() {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(10, 12));
- Marker marker = markerOptions.getMarker();
- assertEquals(marker.getPosition(), new LatLng(10, 12));
- assertEquals(markerOptions.getPosition(), new LatLng(10, 12));
- }
-
- @Test
- public void testTitle() {
- MarkerOptions markerOptions = new MarkerOptions().title("Mapbox").position(new LatLng());
- Marker marker = markerOptions.getMarker();
- assertEquals(marker.getTitle(), "Mapbox");
- assertEquals(markerOptions.getTitle(), "Mapbox");
- }
-
- @Test
- public void testSnippet() {
- MarkerOptions markerOptions = new MarkerOptions().snippet("Mapbox").position(new LatLng());
- Marker marker = markerOptions.getMarker();
- assertEquals(marker.getSnippet(), "Mapbox");
- }
-
- @Test
- public void testBuilder() {
- Marker marker = new MarkerOptions().title("title").snippet("snippet").position(new LatLng(10, 12)).getMarker();
- assertEquals(marker.getSnippet(), "snippet");
-
- assertEquals(marker.getPosition(), new LatLng(10, 12));
- }
-
- @Test
- public void testIcon() {
- Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_4444);
- Icon icon = IconFactory.recreate("test", bitmap);
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng()).icon(icon);
- Marker marker = markerOptions.getMarker();
- assertEquals("Icon should match", icon, marker.getIcon());
- assertEquals("Icon should match", icon, markerOptions.getIcon());
- }
-
- @Test
- public void testHashCode() {
- Marker marker = new MarkerOptions().position(new LatLng()).getMarker();
- assertEquals("hash code should match", marker.hashCode(), 0);
- }
-
- @Test
- public void testHashCodeBuilder() {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(10, 12));
- assertEquals("hash code should match", markerOptions.hashCode(), 579999617);
- }
-
- @Test
- public void testEquals() {
- Marker markerOne = new MarkerOptions().position(new LatLng(0, 0)).getMarker();
- Marker markerTwo = new MarkerOptions().position(new LatLng(0, 0)).getMarker();
- assertEquals(markerOne, markerTwo);
- }
-
- @Test
- public void testEqualityDifferentLocation() {
- MarkerOptions marker = new MarkerOptions().position(new LatLng(0, 0));
- MarkerOptions other = new MarkerOptions().position(new LatLng(1, 0));
- assertNotEquals("Should not match", other, marker);
- }
-
-
- @Test
- public void testEqualityDifferentSnippet() {
- MarkerOptions marker = new MarkerOptions().snippet("s");
- MarkerOptions other = new MarkerOptions();
- assertNotEquals("Should not match", other, marker);
- }
-
- @Test
- public void testEqualityDifferentIcon() {
- MarkerOptions marker = new MarkerOptions().icon(mock(Icon.class));
- MarkerOptions other = new MarkerOptions();
- assertNotEquals("Should not match", other, marker);
- }
-
- @Test
- public void testEqualityDifferentTitle() {
- MarkerOptions marker = new MarkerOptions().title("t");
- MarkerOptions other = new MarkerOptions();
- assertNotEquals("Should not match", other, marker);
- }
-
- @Test
- public void testEqualsItself() {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(0, 0));
- Marker marker = markerOptions.getMarker();
- assertEquals("Marker should match", marker, marker);
- assertEquals("MarkerOptions should match", markerOptions, markerOptions);
- }
-
- @Test
- public void testNotEquals() {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(0, 0));
- Marker marker = markerOptions.getMarker();
- assertNotEquals("MarkerOptions should match", markerOptions, new Object());
- assertNotEquals("Marker should match", marker, new Object());
- }
-
- @Test
- public void testEqualityBuilder() {
- MarkerOptions markerOne = new MarkerOptions().position(new LatLng(0, 0));
- MarkerOptions markerTwo = new MarkerOptions().position(new LatLng(0, 0));
- assertEquals(markerOne, markerTwo);
- }
-
- @Test
- public void testToString() {
- Marker marker = new MarkerOptions().position(new LatLng(0, 0)).getMarker();
- assertEquals(marker.toString(), "Marker [position[" + "LatLng [latitude=0.0, longitude=0.0, altitude=0.0]" + "]]");
- }
-
- @Test
- public void testParcelable() {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng()).title("t").snippet("s");
- Parcelable parcelable = MockParcel.obtain(markerOptions);
- assertEquals("Parcel should match original object", parcelable, markerOptions);
- }
+ @Test
+ public void testSanity() {
+ MarkerOptions markerOptions = new MarkerOptions();
+ assertNotNull("markerOptions should not be null", markerOptions);
+ }
+
+ @Test
+ public void testMarker() {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ assertNotNull("marker should not be null", markerOptions.getMarker());
+ }
+
+ @Test(expected = InvalidMarkerPositionException.class)
+ public void testInvalidMarker() {
+ new MarkerOptions().getMarker();
+ }
+
+ @Test
+ public void testPosition() {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(10, 12));
+ Marker marker = markerOptions.getMarker();
+ assertEquals(marker.getPosition(), new LatLng(10, 12));
+ assertEquals(markerOptions.getPosition(), new LatLng(10, 12));
+ }
+
+ @Test
+ public void testTitle() {
+ MarkerOptions markerOptions = new MarkerOptions().title("Mapbox").position(new LatLng());
+ Marker marker = markerOptions.getMarker();
+ assertEquals(marker.getTitle(), "Mapbox");
+ assertEquals(markerOptions.getTitle(), "Mapbox");
+ }
+
+ @Test
+ public void testSnippet() {
+ MarkerOptions markerOptions = new MarkerOptions().snippet("Mapbox").position(new LatLng());
+ Marker marker = markerOptions.getMarker();
+ assertEquals(marker.getSnippet(), "Mapbox");
+ }
+
+ @Test
+ public void testBuilder() {
+ Marker marker = new MarkerOptions().title("title").snippet("snippet").position(new LatLng(10, 12)).getMarker();
+ assertEquals(marker.getSnippet(), "snippet");
+
+ assertEquals(marker.getPosition(), new LatLng(10, 12));
+ }
+
+ @Test
+ public void testIcon() {
+ Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_4444);
+ Icon icon = IconFactory.recreate("test", bitmap);
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng()).icon(icon);
+ Marker marker = markerOptions.getMarker();
+ assertEquals("Icon should match", icon, marker.getIcon());
+ assertEquals("Icon should match", icon, markerOptions.getIcon());
+ }
+
+ @Test
+ public void testHashCode() {
+ Marker marker = new MarkerOptions().position(new LatLng()).getMarker();
+ assertEquals("hash code should match", marker.hashCode(), 0);
+ }
+
+ @Test
+ public void testHashCodeBuilder() {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(10, 12));
+ assertEquals("hash code should match", markerOptions.hashCode(), 579999617);
+ }
+
+ @Test
+ public void testEquals() {
+ Marker markerOne = new MarkerOptions().position(new LatLng(0, 0)).getMarker();
+ Marker markerTwo = new MarkerOptions().position(new LatLng(0, 0)).getMarker();
+ assertEquals(markerOne, markerTwo);
+ }
+
+ @Test
+ public void testEqualityDifferentLocation() {
+ MarkerOptions marker = new MarkerOptions().position(new LatLng(0, 0));
+ MarkerOptions other = new MarkerOptions().position(new LatLng(1, 0));
+ assertNotEquals("Should not match", other, marker);
+ }
+
+
+ @Test
+ public void testEqualityDifferentSnippet() {
+ MarkerOptions marker = new MarkerOptions().snippet("s");
+ MarkerOptions other = new MarkerOptions();
+ assertNotEquals("Should not match", other, marker);
+ }
+
+ @Test
+ public void testEqualityDifferentIcon() {
+ MarkerOptions marker = new MarkerOptions().icon(mock(Icon.class));
+ MarkerOptions other = new MarkerOptions();
+ assertNotEquals("Should not match", other, marker);
+ }
+
+ @Test
+ public void testEqualityDifferentTitle() {
+ MarkerOptions marker = new MarkerOptions().title("t");
+ MarkerOptions other = new MarkerOptions();
+ assertNotEquals("Should not match", other, marker);
+ }
+
+ @Test
+ public void testEqualsItself() {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(0, 0));
+ Marker marker = markerOptions.getMarker();
+ assertEquals("Marker should match", marker, marker);
+ assertEquals("MarkerOptions should match", markerOptions, markerOptions);
+ }
+
+ @Test
+ public void testNotEquals() {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(0, 0));
+ Marker marker = markerOptions.getMarker();
+ assertNotEquals("MarkerOptions should match", markerOptions, new Object());
+ assertNotEquals("Marker should match", marker, new Object());
+ }
+
+ @Test
+ public void testEqualityBuilder() {
+ MarkerOptions markerOne = new MarkerOptions().position(new LatLng(0, 0));
+ MarkerOptions markerTwo = new MarkerOptions().position(new LatLng(0, 0));
+ assertEquals(markerOne, markerTwo);
+ }
+
+ @Test
+ public void testToString() {
+ Marker marker = new MarkerOptions().position(new LatLng(0, 0)).getMarker();
+ assertEquals(marker.toString(), "Marker [position[" + "LatLng [latitude=0.0, longitude=0.0, altitude=0.0]" + "]]");
+ }
+
+ @Test
+ public void testParcelable() {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng()).title("t").snippet("s");
+ Parcelable parcelable = MockParcel.obtain(markerOptions);
+ assertEquals("Parcel should match original object", parcelable, markerOptions);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java
index 6cef1898bd..3c52c16422 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java
@@ -23,265 +23,264 @@ import static org.mockito.Mockito.when;
public class MarkerViewTest {
- @Mock
- MapboxMap mapboxMap;
-
- @Mock
- MarkerViewManager markerViewManager;
-
- @Before
- public void beforeTest() {
- MockitoAnnotations.initMocks(this);
- }
-
- @Test
- public void testSanity() {
- MarkerViewOptions markerOptions = new MarkerViewOptions();
- assertNotNull("markerOptions should not be null", markerOptions);
- }
-
- @Test
- public void testMarker() {
- MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng());
- assertNotNull("marker should not be null", markerOptions.getMarker());
- }
-
- @Test(expected = InvalidMarkerPositionException.class)
- public void testInvalidMarker() {
- new MarkerViewOptions().getMarker();
- }
-
- @Test
- public void testPosition() {
- MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng(10, 12));
- MarkerView marker = markerOptions.getMarker();
- assertEquals(marker.getPosition(), new LatLng(10, 12));
- assertEquals(markerOptions.getPosition(), new LatLng(10, 12));
- }
-
- @Test
- public void testSnippet() {
- MarkerViewOptions markerOptions = new MarkerViewOptions().snippet("Mapbox").position(new LatLng());
- MarkerView marker = markerOptions.getMarker();
- assertEquals(marker.getSnippet(), "Mapbox");
- }
-
- @Test
- public void testTitle() {
- MarkerViewOptions markerOptions = new MarkerViewOptions().title("Mapbox").position(new LatLng());
- MarkerView marker = markerOptions.getMarker();
- assertEquals(marker.getTitle(), "Mapbox");
- assertEquals(markerOptions.getTitle(), "Mapbox");
- }
-
- @Test
- public void testFlat() {
- MarkerViewOptions markerOptions = new MarkerViewOptions().flat(true).position(new LatLng());
- MarkerView marker = markerOptions.getMarker();
- assertTrue("flat should be true", marker.isFlat());
- }
-
- @Test
- public void testFlatDefault() {
- assertFalse("default value of flat should be false", new MarkerViewOptions().position(new LatLng()).getMarker().isFlat());
- }
-
- @Test
- public void testAnchor() {
- float anchorU = 1;
- float anchorV = 1;
- MarkerViewOptions markerOptions = new MarkerViewOptions().anchor(anchorU, anchorV).position(new LatLng());
- MarkerView marker = markerOptions.getMarker();
- assertEquals("anchorU should match ", anchorU, marker.getAnchorU(), 0);
- assertEquals("anchorU should match ", anchorV, marker.getAnchorV(), 0);
- }
-
- @Test
- public void testAnchorDefault() {
- MarkerView marker = new MarkerViewOptions().position(new LatLng()).getMarker();
- assertEquals("anchorU should match ", 0.5, marker.getAnchorU(), 0);
- assertEquals("anchorU should match ", 1, marker.getAnchorV(), 0);
- }
-
- @Test
- public void testInfoWindowAnchor() {
- float anchorU = 1;
- float anchorV = 1;
- MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).infoWindowAnchor(anchorU, anchorV);
- MarkerView marker = markerOptions.getMarker();
- assertEquals("anchorU should match ", 1, marker.getInfoWindowAnchorU(), 0);
- assertEquals("anchorU should match ", 1, marker.getInfoWindowAnchorV(), 0);
- }
-
- @Test
- public void testInfoWindowAnchorDefault() {
- MarkerView marker = new MarkerViewOptions().position(new LatLng()).getMarker();
- assertEquals("anchorU should match ", 0.5, marker.getInfoWindowAnchorU(), 0);
- assertEquals("anchorU should match ", 0, marker.getInfoWindowAnchorV(), 0);
- }
-
- @Test
- public void testRotation() {
- int rotation = 90;
- MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).rotation(rotation);
- MarkerView marker = markerOptions.getMarker();
- assertEquals("rotation should match ", rotation, marker.getRotation(), 0);
- }
-
- @Test
- public void testRotationAboveMax() {
- MarkerViewOptions markerOptions = new MarkerViewOptions().rotation(390).position(new LatLng());
- MarkerView marker = markerOptions.getMarker();
- assertEquals(marker.getRotation(), 30, 0);
- }
-
- @Test
- public void testRotationBelowMin() {
- MarkerViewOptions markerOptions = new MarkerViewOptions().rotation(-10).position(new LatLng());
- MarkerView marker = markerOptions.getMarker();
- assertEquals(marker.getRotation(), 350, 0);
- }
-
- @Test
- public void testRotationUpdatePositive() {
- float startRotation = 45;
- float endRotation = 180;
- float animationValue = 135;
-
- // allow calls to our mock
- when(mapboxMap.getMarkerViewManager()).thenReturn(markerViewManager);
-
- MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).rotation(startRotation);
- MarkerView marker = markerOptions.getMarker();
- marker.setMapboxMap(mapboxMap);
-
- marker.setRotation(endRotation);
- verify(markerViewManager, times(1)).animateRotationBy(marker, animationValue);
- }
-
- @Test
- public void testRotationUpdateNegative() {
- float startRotation = 10;
- float endRotation = 270;
- float animationValue = -100;
-
- // allow calls to our mock
- when(mapboxMap.getMarkerViewManager()).thenReturn(markerViewManager);
-
- MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).rotation(startRotation);
- MarkerView marker = markerOptions.getMarker();
- marker.setMapboxMap(mapboxMap);
-
- marker.setRotation(endRotation);
- verify(markerViewManager, times(1)).animateRotationBy(marker, animationValue);
- }
-
- @Test
- public void testRotationUpdateMax() {
- float startRotation = 359;
- float endRotation = 0;
- float animationValue = 1;
-
- // allow calls to our mock
- when(mapboxMap.getMarkerViewManager()).thenReturn(markerViewManager);
-
- MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).rotation(startRotation);
- MarkerView marker = markerOptions.getMarker();
- marker.setMapboxMap(mapboxMap);
-
- marker.setRotation(endRotation);
- verify(markerViewManager, times(1)).animateRotationBy(marker, animationValue);
- }
-
- @Test
- public void testRotationUpdateMin() {
- float startRotation = 0;
- float endRotation = 359;
- float animationValue = -1;
-
- // allow calls to our mock
- when(mapboxMap.getMarkerViewManager()).thenReturn(markerViewManager);
-
- MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).rotation(startRotation);
- MarkerView marker = markerOptions.getMarker();
- marker.setMapboxMap(mapboxMap);
-
- marker.setRotation(endRotation);
- verify(markerViewManager, times(1)).animateRotationBy(marker, animationValue);
- }
-
- @Test
- public void testVisible() {
- boolean visible = false;
- MarkerViewOptions markerOptions = new MarkerViewOptions().visible(visible).position(new LatLng());
- MarkerView marker = markerOptions.getMarker();
- assertEquals("visible should match ", visible, marker.isVisible());
- }
-
- @Test
- public void testVisibleDefault() {
- assertTrue(new MarkerViewOptions().position(new LatLng()).getMarker().isVisible());
- }
-
- @Test
- public void testBuilder() {
- MarkerView marker = new MarkerViewOptions().title("title").snippet("snippet").position(new LatLng(10, 12)).getMarker();
- assertEquals(marker.getSnippet(), "snippet");
- assertEquals(marker.getPosition(), new LatLng(10, 12));
- }
-
- @Test
- public void testHashCode() {
- MarkerView marker = new MarkerViewOptions().position(new LatLng()).getMarker();
- assertEquals("hash code should match", marker.hashCode(), 0);
- }
-
- @Test
- public void testHashCodeBuilder() {
- MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng(10, 12));
- assertEquals("hash code should match", markerOptions.hashCode(), 0);
- }
-
- @Test
- public void testEquals() {
- MarkerView markerOne = new MarkerViewOptions().position(new LatLng(0, 0)).getMarker();
- MarkerView markerTwo = new MarkerViewOptions().position(new LatLng(0, 0)).getMarker();
- assertEquals(markerOne, markerTwo);
- }
-
- @Test
- public void testEqualsItself() {
- MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng(0, 0));
- MarkerView marker = markerOptions.getMarker();
- assertEquals("MarkerView should match", marker, marker);
- assertEquals("MarkerViewOptions should match", markerOptions, markerOptions);
- }
-
- @Test
- public void testNotEquals() {
- MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng(0, 0));
- MarkerView marker = markerOptions.getMarker();
- assertNotEquals("MarkerViewOptions should match", markerOptions, new Object());
- assertNotEquals("MarkerView should match", marker, new Object());
- }
-
- @Test
- public void testEqualityBuilder() {
- MarkerViewOptions markerOne = new MarkerViewOptions().position(new LatLng(0, 0));
- MarkerViewOptions markerTwo = new MarkerViewOptions().position(new LatLng(0, 0));
- assertEquals(markerOne, markerTwo);
- }
-
- @Test
- public void testToString() {
- MarkerView marker = new MarkerViewOptions().position(new LatLng(0, 0)).getMarker();
- assertEquals(marker.toString(), "MarkerView [position[" + "LatLng [latitude=0.0, longitude=0.0, altitude=0.0]" + "]]");
- }
-
- @Test
- public void testParcelable() {
- MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).title("t").snippet("s");
- Parcelable parcelable = MockParcel.obtain(markerOptions);
- assertEquals("Parcel should match original object", parcelable, markerOptions);
- }
+ @Mock
+ MapboxMap mapboxMap;
+
+ @Mock
+ MarkerViewManager markerViewManager;
+
+ @Before
+ public void beforeTest() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testSanity() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions();
+ assertNotNull("markerOptions should not be null", markerOptions);
+ }
+
+ @Test
+ public void testMarker() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng());
+ assertNotNull("marker should not be null", markerOptions.getMarker());
+ }
+
+ @Test(expected = InvalidMarkerPositionException.class)
+ public void testInvalidMarker() {
+ new MarkerViewOptions().getMarker();
+ }
+
+ @Test
+ public void testPosition() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng(10, 12));
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals(marker.getPosition(), new LatLng(10, 12));
+ assertEquals(markerOptions.getPosition(), new LatLng(10, 12));
+ }
+
+ @Test
+ public void testSnippet() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().snippet("Mapbox").position(new LatLng());
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals(marker.getSnippet(), "Mapbox");
+ }
+
+ @Test
+ public void testTitle() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().title("Mapbox").position(new LatLng());
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals(marker.getTitle(), "Mapbox");
+ assertEquals(markerOptions.getTitle(), "Mapbox");
+ }
+
+ @Test
+ public void testFlat() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().flat(true).position(new LatLng());
+ MarkerView marker = markerOptions.getMarker();
+ assertTrue("flat should be true", marker.isFlat());
+ }
+
+ @Test
+ public void testFlatDefault() {
+ assertFalse("default value of flat should be false", new MarkerViewOptions().position(
+ new LatLng()).getMarker().isFlat());
+ }
+
+ @Test
+ public void testAnchor() {
+ float anchorU = 1;
+ float anchorV = 1;
+ MarkerViewOptions markerOptions = new MarkerViewOptions().anchor(anchorU, anchorV).position(new LatLng());
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("anchorU should match ", anchorU, marker.getAnchorU(), 0);
+ assertEquals("anchorU should match ", anchorV, marker.getAnchorV(), 0);
+ }
+
+ @Test
+ public void testAnchorDefault() {
+ MarkerView marker = new MarkerViewOptions().position(new LatLng()).getMarker();
+ assertEquals("anchorU should match ", 0.5, marker.getAnchorU(), 0);
+ assertEquals("anchorU should match ", 1, marker.getAnchorV(), 0);
+ }
+
+ @Test
+ public void testInfoWindowAnchor() {
+ float anchorU = 1;
+ float anchorV = 1;
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).infoWindowAnchor(anchorU, anchorV);
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("anchorU should match ", 1, marker.getInfoWindowAnchorU(), 0);
+ assertEquals("anchorU should match ", 1, marker.getInfoWindowAnchorV(), 0);
+ }
+
+ @Test
+ public void testInfoWindowAnchorDefault() {
+ MarkerView marker = new MarkerViewOptions().position(new LatLng()).getMarker();
+ assertEquals("anchorU should match ", 0.5, marker.getInfoWindowAnchorU(), 0);
+ assertEquals("anchorU should match ", 0, marker.getInfoWindowAnchorV(), 0);
+ }
+
+ @Test
+ public void testRotation() {
+ int rotation = 90;
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).rotation(rotation);
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("rotation should match ", rotation, marker.getRotation(), 0);
+ }
+
+ @Test
+ public void testRotationAboveMax() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().rotation(390).position(new LatLng());
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals(marker.getRotation(), 30, 0);
+ }
+
+ @Test
+ public void testRotationBelowMin() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().rotation(-10).position(new LatLng());
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals(marker.getRotation(), 350, 0);
+ }
+
+ @Test
+ public void testRotationUpdatePositive() {
+ float startRotation = 45;
+ float endRotation = 180;
+
+ // allow calls to our mock
+ when(mapboxMap.getMarkerViewManager()).thenReturn(markerViewManager);
+
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).rotation(startRotation);
+ MarkerView marker = markerOptions.getMarker();
+ marker.setMapboxMap(mapboxMap);
+
+ marker.setRotation(endRotation);
+ verify(markerViewManager, times(1)).animateRotationBy(marker, endRotation);
+ }
+
+ @Test
+ public void testRotationUpdateNegative() {
+ float startRotation = 10;
+ float endRotation = 270;
+
+ // allow calls to our mock
+ when(mapboxMap.getMarkerViewManager()).thenReturn(markerViewManager);
+
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).rotation(startRotation);
+ MarkerView marker = markerOptions.getMarker();
+ marker.setMapboxMap(mapboxMap);
+
+ marker.setRotation(endRotation);
+ verify(markerViewManager, times(1)).animateRotationBy(marker, endRotation);
+ }
+
+ @Test
+ public void testRotationUpdateMax() {
+ float startRotation = 359;
+ float endRotation = 0;
+
+ // allow calls to our mock
+ when(mapboxMap.getMarkerViewManager()).thenReturn(markerViewManager);
+
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).rotation(startRotation);
+ MarkerView marker = markerOptions.getMarker();
+ marker.setMapboxMap(mapboxMap);
+
+ marker.setRotation(endRotation);
+ verify(markerViewManager, times(1)).animateRotationBy(marker, 0);
+ }
+
+ @Test
+ public void testRotationUpdateMin() {
+ float startRotation = 0;
+ float endRotation = 359;
+
+ // allow calls to our mock
+ when(mapboxMap.getMarkerViewManager()).thenReturn(markerViewManager);
+
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).rotation(startRotation);
+ MarkerView marker = markerOptions.getMarker();
+ marker.setMapboxMap(mapboxMap);
+
+ marker.setRotation(endRotation);
+ verify(markerViewManager, times(1)).animateRotationBy(marker, endRotation);
+ }
+
+ @Test
+ public void testVisible() {
+ boolean visible = false;
+ MarkerViewOptions markerOptions = new MarkerViewOptions().visible(visible).position(new LatLng());
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("visible should match ", visible, marker.isVisible());
+ }
+
+ @Test
+ public void testVisibleDefault() {
+ assertTrue(new MarkerViewOptions().position(new LatLng()).getMarker().isVisible());
+ }
+
+ @Test
+ public void testBuilder() {
+ MarkerView marker = new MarkerViewOptions().title("title").snippet("snippet").position(
+ new LatLng(10, 12)).getMarker();
+ assertEquals(marker.getSnippet(), "snippet");
+ assertEquals(marker.getPosition(), new LatLng(10, 12));
+ }
+
+ @Test
+ public void testHashCode() {
+ MarkerView marker = new MarkerViewOptions().position(new LatLng()).getMarker();
+ assertEquals("hash code should match", marker.hashCode(), 0);
+ }
+
+ @Test
+ public void testHashCodeBuilder() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng(10, 12));
+ assertEquals("hash code should match", markerOptions.hashCode(), 0);
+ }
+
+ @Test
+ public void testEquals() {
+ MarkerView markerOne = new MarkerViewOptions().position(new LatLng(0, 0)).getMarker();
+ MarkerView markerTwo = new MarkerViewOptions().position(new LatLng(0, 0)).getMarker();
+ assertEquals(markerOne, markerTwo);
+ }
+
+ @Test
+ public void testEqualsItself() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng(0, 0));
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("MarkerView should match", marker, marker);
+ assertEquals("MarkerViewOptions should match", markerOptions, markerOptions);
+ }
+
+ @Test
+ public void testNotEquals() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng(0, 0));
+ MarkerView marker = markerOptions.getMarker();
+ assertNotEquals("MarkerViewOptions should match", markerOptions, new Object());
+ assertNotEquals("MarkerView should match", marker, new Object());
+ }
+
+ @Test
+ public void testEqualityBuilder() {
+ MarkerViewOptions markerOne = new MarkerViewOptions().position(new LatLng(0, 0));
+ MarkerViewOptions markerTwo = new MarkerViewOptions().position(new LatLng(0, 0));
+ assertEquals(markerOne, markerTwo);
+ }
+
+ @Test
+ public void testToString() {
+ MarkerView marker = new MarkerViewOptions().position(new LatLng(0, 0)).getMarker();
+ assertEquals(marker.toString(), "MarkerView [position["
+ + "LatLng [latitude=0.0, longitude=0.0, altitude=0.0]" + "]]");
+ }
+
+ @Test
+ public void testParcelable() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).title("t").snippet("s");
+ Parcelable parcelable = MockParcel.obtain(markerOptions);
+ assertEquals("Parcel should match original object", parcelable, markerOptions);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/PolygonTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/PolygonTest.java
index 744bf55c07..3933c68887 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/PolygonTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/PolygonTest.java
@@ -1,9 +1,5 @@
package com.mapbox.mapboxsdk.annotations;
-import com.mapbox.mapboxsdk.annotations.Polygon;
-import com.mapbox.mapboxsdk.annotations.PolygonOptions;
-import com.mapbox.mapboxsdk.annotations.Polyline;
-import com.mapbox.mapboxsdk.annotations.PolylineOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import org.junit.Test;
@@ -16,64 +12,64 @@ import static org.junit.Assert.assertNotNull;
public class PolygonTest {
- @Test
- public void testSanity() {
- PolygonOptions polygonOptions = new PolygonOptions();
- assertNotNull("polygonOptions should not be null", polygonOptions);
- }
+ @Test
+ public void testSanity() {
+ PolygonOptions polygonOptions = new PolygonOptions();
+ assertNotNull("polygonOptions should not be null", polygonOptions);
+ }
- @Test
- public void testPolygon() {
- Polygon polygon = new PolygonOptions().getPolygon();
- assertNotNull("polyline should not be null", polygon);
- }
+ @Test
+ public void testPolygon() {
+ Polygon polygon = new PolygonOptions().getPolygon();
+ assertNotNull("polyline should not be null", polygon);
+ }
- @Test
- public void testAlpha() {
- Polygon polygon = new PolygonOptions().alpha(0.5f).getPolygon();
- assertEquals(0.5f, polygon.getAlpha(), 0.0f);
- }
+ @Test
+ public void testAlpha() {
+ Polygon polygon = new PolygonOptions().alpha(0.5f).getPolygon();
+ assertEquals(0.5f, polygon.getAlpha(), 0.0f);
+ }
- @Test
- public void testStrokeColor() {
- Polygon polygon = new PolygonOptions().strokeColor(1).getPolygon();
- assertEquals(1, polygon.getStrokeColor());
- }
+ @Test
+ public void testStrokeColor() {
+ Polygon polygon = new PolygonOptions().strokeColor(1).getPolygon();
+ assertEquals(1, polygon.getStrokeColor());
+ }
- @Test
- public void testFillColor() {
- Polygon polygon = new PolygonOptions().fillColor(1).getPolygon();
- assertEquals(1, polygon.getFillColor());
- }
+ @Test
+ public void testFillColor() {
+ Polygon polygon = new PolygonOptions().fillColor(1).getPolygon();
+ assertEquals(1, polygon.getFillColor());
+ }
- @Test
- public void testLatLng() {
- Polygon polygon = new PolygonOptions().add(new LatLng(0, 0)).getPolygon();
- assertNotNull("points should not be null", polygon.getPoints());
- assertEquals(new LatLng(0, 0), polygon.getPoints().get(0));
- }
+ @Test
+ public void testLatLng() {
+ Polygon polygon = new PolygonOptions().add(new LatLng(0, 0)).getPolygon();
+ assertNotNull("points should not be null", polygon.getPoints());
+ assertEquals(new LatLng(0, 0), polygon.getPoints().get(0));
+ }
- @Test
- public void testAddAllLatLng() {
- List<LatLng> coordinates = new ArrayList<>();
- coordinates.add(new LatLng(0, 0));
- Polygon polygon = new PolygonOptions().addAll(coordinates).getPolygon();
- assertNotNull(polygon.getPoints());
- assertEquals(new LatLng(0, 0), polygon.getPoints().get(0));
- }
+ @Test
+ public void testAddAllLatLng() {
+ List<LatLng> coordinates = new ArrayList<>();
+ coordinates.add(new LatLng(0, 0));
+ Polygon polygon = new PolygonOptions().addAll(coordinates).getPolygon();
+ assertNotNull(polygon.getPoints());
+ assertEquals(new LatLng(0, 0), polygon.getPoints().get(0));
+ }
- @Test
- public void testBuilder() {
- PolylineOptions polylineOptions = new PolylineOptions();
- polylineOptions.width(1.0f);
- polylineOptions.color(2);
- polylineOptions.add(new LatLng(0, 0));
+ @Test
+ public void testBuilder() {
+ PolylineOptions polylineOptions = new PolylineOptions();
+ polylineOptions.width(1.0f);
+ polylineOptions.color(2);
+ polylineOptions.add(new LatLng(0, 0));
- Polyline polyline = polylineOptions.getPolyline();
- assertEquals(1.0f, polyline.getWidth(), 0);
- assertEquals(2, polyline.getColor());
- assertNotNull("Points should not be null", polyline.getPoints());
- assertEquals(new LatLng(0, 0), polyline.getPoints().get(0));
- }
+ Polyline polyline = polylineOptions.getPolyline();
+ assertEquals(1.0f, polyline.getWidth(), 0);
+ assertEquals(2, polyline.getColor());
+ assertNotNull("Points should not be null", polyline.getPoints());
+ assertEquals(new LatLng(0, 0), polyline.getPoints().get(0));
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/PolylineTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/PolylineTest.java
index b95c9dba2a..54bb0e8cf4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/PolylineTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/PolylineTest.java
@@ -1,7 +1,5 @@
package com.mapbox.mapboxsdk.annotations;
-import com.mapbox.mapboxsdk.annotations.Polyline;
-import com.mapbox.mapboxsdk.annotations.PolylineOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import org.junit.Test;
@@ -14,64 +12,64 @@ import static org.junit.Assert.assertNotNull;
public class PolylineTest {
- @Test
- public void testSanity() {
- PolylineOptions polylineOptions = new PolylineOptions();
- assertNotNull("polylineOptions should not be null", polylineOptions);
- }
+ @Test
+ public void testSanity() {
+ PolylineOptions polylineOptions = new PolylineOptions();
+ assertNotNull("polylineOptions should not be null", polylineOptions);
+ }
- @Test
- public void testPolyline() {
- Polyline polyline = new PolylineOptions().getPolyline();
- assertNotNull("polyline should not be null", polyline);
- }
+ @Test
+ public void testPolyline() {
+ Polyline polyline = new PolylineOptions().getPolyline();
+ assertNotNull("polyline should not be null", polyline);
+ }
- @Test
- public void testAlpha() {
- Polyline polyline = new PolylineOptions().alpha(0.2f).getPolyline();
- assertEquals(0.2f, polyline.getAlpha(), 0.0f);
- }
+ @Test
+ public void testAlpha() {
+ Polyline polyline = new PolylineOptions().alpha(0.2f).getPolyline();
+ assertEquals(0.2f, polyline.getAlpha(), 0.0f);
+ }
- @Test
- public void testWidth() {
- Polyline polyline = new PolylineOptions().width(1).getPolyline();
- assertEquals(1.0f, polyline.getWidth(), 0);
- }
+ @Test
+ public void testWidth() {
+ Polyline polyline = new PolylineOptions().width(1).getPolyline();
+ assertEquals(1.0f, polyline.getWidth(), 0);
+ }
- @Test
- public void testColor() {
- Polyline polyline = new PolylineOptions().color(1).getPolyline();
- assertEquals(1, polyline.getColor());
- }
+ @Test
+ public void testColor() {
+ Polyline polyline = new PolylineOptions().color(1).getPolyline();
+ assertEquals(1, polyline.getColor());
+ }
- @Test
- public void testAddLatLng() {
- Polyline polyline = new PolylineOptions().add(new LatLng(0, 0)).getPolyline();
- assertNotNull("Points should not be null", polyline.getPoints());
- assertEquals(new LatLng(0, 0), polyline.getPoints().get(0));
- }
+ @Test
+ public void testAddLatLng() {
+ Polyline polyline = new PolylineOptions().add(new LatLng(0, 0)).getPolyline();
+ assertNotNull("Points should not be null", polyline.getPoints());
+ assertEquals(new LatLng(0, 0), polyline.getPoints().get(0));
+ }
- @Test
- public void testAddAllLatLng() {
- List<LatLng> coordinates = new ArrayList<>();
- coordinates.add(new LatLng(0, 0));
- Polyline polyline = new PolylineOptions().addAll(coordinates).getPolyline();
- assertNotNull(polyline.getPoints());
- assertEquals(new LatLng(0, 0), polyline.getPoints().get(0));
- }
+ @Test
+ public void testAddAllLatLng() {
+ List<LatLng> coordinates = new ArrayList<>();
+ coordinates.add(new LatLng(0, 0));
+ Polyline polyline = new PolylineOptions().addAll(coordinates).getPolyline();
+ assertNotNull(polyline.getPoints());
+ assertEquals(new LatLng(0, 0), polyline.getPoints().get(0));
+ }
- @Test
- public void testBuilder() {
- PolylineOptions polylineOptions = new PolylineOptions();
- polylineOptions.width(1.0f);
- polylineOptions.color(2);
- polylineOptions.add(new LatLng(0, 0));
+ @Test
+ public void testBuilder() {
+ PolylineOptions polylineOptions = new PolylineOptions();
+ polylineOptions.width(1.0f);
+ polylineOptions.color(2);
+ polylineOptions.add(new LatLng(0, 0));
- Polyline polyline = polylineOptions.getPolyline();
- assertEquals(1.0f, polyline.getWidth(), 0);
- assertEquals(2, polyline.getColor());
- assertNotNull("Points should not be null", polyline.getPoints());
- assertEquals(new LatLng(0, 0), polyline.getPoints().get(0));
- }
+ Polyline polyline = polylineOptions.getPolyline();
+ assertEquals(1.0f, polyline.getWidth(), 0);
+ assertEquals(2, polyline.getColor());
+ assertNotNull("Points should not be null", polyline.getPoints());
+ assertEquals(new LatLng(0, 0), polyline.getPoints().get(0));
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java
index bce020255e..a8aad8d639 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java
@@ -18,108 +18,109 @@ import static org.mockito.Mockito.when;
public class CameraPositionTest {
- private static final double DELTA = 1e-15;
-
- @Test
- public void testSanity() {
- LatLng latLng = new LatLng(1, 2);
- CameraPosition cameraPosition = new CameraPosition(latLng, 3, 4, 5);
- assertNotNull("cameraPosition should not be null", cameraPosition);
- }
-
- @Test
- public void testDefaultTypedArrayBuilder() {
- TypedArray typedArray = null;
- CameraPosition cameraPosition = new CameraPosition.Builder(typedArray).build();
- assertEquals("bearing should match", -1, cameraPosition.bearing, DELTA);
- assertEquals("latlng should match", null, cameraPosition.target);
- assertEquals("tilt should match", -1, cameraPosition.tilt, DELTA);
- assertEquals("zoom should match", -1, cameraPosition.zoom, DELTA);
- }
-
- @Test
- public void testTypedArrayBuilder() {
- float bearing = 180;
- float zoom = 12;
- float latitude = 10;
- float longitude = 11;
- float tilt = 44;
-
- TypedArray typedArray = mock(TypedArray.class);
- when(typedArray.getFloat(R.styleable.MapView_direction, 0.0f)).thenReturn(bearing);
- when(typedArray.getFloat(R.styleable.MapView_center_latitude, 0.0f)).thenReturn(latitude);
- when(typedArray.getFloat(R.styleable.MapView_center_longitude, 0.0f)).thenReturn(longitude);
- when(typedArray.getFloat(R.styleable.MapView_zoom, 0.0f)).thenReturn(zoom);
- when(typedArray.getFloat(R.styleable.MapView_tilt, 0.0f)).thenReturn(tilt);
- doNothing().when(typedArray).recycle();
-
- CameraPosition cameraPosition = new CameraPosition.Builder(typedArray).build();
- assertEquals("bearing should match", bearing, cameraPosition.bearing, DELTA);
- assertEquals("latlng should match", new LatLng(latitude, longitude), cameraPosition.target);
- assertEquals("tilt should match", tilt, cameraPosition.tilt, DELTA);
- assertEquals("zoom should match", zoom, cameraPosition.zoom, DELTA);
- }
-
- @Test
- public void testJniBuilder() {
- double bearing = 180;
- double zoom = 12;
- double latitude = 10;
- double longitude = 11;
- double tilt = 44;
-
- double[] cameraVars = new double[]{latitude, longitude, bearing, tilt, zoom};
- CameraPosition cameraPosition = new CameraPosition.Builder(cameraVars).build();
- assertEquals("bearing should match", bearing, cameraPosition.bearing, DELTA);
- assertEquals("latlng should match", new LatLng(latitude, longitude), cameraPosition.target);
- assertEquals("tilt should match", tilt, cameraPosition.tilt, DELTA);
- assertEquals("zoom should match", zoom, cameraPosition.zoom, DELTA);
- }
-
- @Test
- public void testToString() {
- LatLng latLng = new LatLng(1, 2);
- CameraPosition cameraPosition = new CameraPosition(latLng, 3, 4, 5);
- assertEquals("toString should match", "Target: LatLng [latitude=1.0, longitude=2.0, altitude=0.0], Zoom:3.0, Bearing:5.0, Tilt:4.0", cameraPosition.toString());
- }
-
- @Test
- public void testHashcode() {
- LatLng latLng = new LatLng(1, 2);
- CameraPosition cameraPosition = new CameraPosition(latLng, 3, 4, 5);
- assertEquals("hashCode should match", -1007681505, cameraPosition.hashCode());
- }
-
- @Test
- public void testZoomUpdateBuilder() {
- float zoomLevel = 5;
- CameraPosition.Builder builder = new CameraPosition.Builder(
- (CameraUpdateFactory.ZoomUpdate) CameraUpdateFactory.zoomTo(zoomLevel));
- assertEquals("zoom should match", zoomLevel, builder.build().zoom, 0);
- }
-
- @Test
- public void testEquals() {
- LatLng latLng = new LatLng(1, 2);
- CameraPosition cameraPosition = new CameraPosition(latLng, 3, 4, 5);
- CameraPosition cameraPositionBearing = new CameraPosition(latLng, 3, 4, 9);
- CameraPosition cameraPositionTilt = new CameraPosition(latLng, 3, 9, 5);
- CameraPosition cameraPositionZoom = new CameraPosition(latLng, 9, 4, 5);
- CameraPosition cameraPositionTarget = new CameraPosition(new LatLng(), 3, 4, 5);
-
- assertEquals("cameraPosition should match itself", cameraPosition, cameraPosition);
- assertNotEquals("cameraPosition should not match null", null, cameraPosition);
- assertNotEquals("cameraPosition should not match object", new Object(), cameraPosition);
- assertNotEquals("cameraPosition should not match for bearing", cameraPositionBearing, cameraPosition);
- assertNotEquals("cameraPosition should not match for tilt", cameraPositionTilt, cameraPosition);
- assertNotEquals("cameraPosition should not match for zoom", cameraPositionZoom, cameraPosition);
- assertNotEquals("cameraPosition should not match for target", cameraPositionTarget, cameraPosition);
- }
-
- @Test
- public void testParcelable() {
- CameraPosition object = new CameraPosition(new LatLng(1, 2), 3, 4, 5);
- Parcelable parcelable = MockParcel.obtain(object);
- assertEquals("Parcel should match original object", parcelable, object);
- }
-}
+ private static final double DELTA = 1e-15;
+
+ @Test
+ public void testSanity() {
+ LatLng latLng = new LatLng(1, 2);
+ CameraPosition cameraPosition = new CameraPosition(latLng, 3, 4, 5);
+ assertNotNull("cameraPosition should not be null", cameraPosition);
+ }
+
+ @Test
+ public void testDefaultTypedArrayBuilder() {
+ TypedArray typedArray = null;
+ CameraPosition cameraPosition = new CameraPosition.Builder(typedArray).build();
+ assertEquals("bearing should match", -1, cameraPosition.bearing, DELTA);
+ assertEquals("latlng should match", null, cameraPosition.target);
+ assertEquals("tilt should match", -1, cameraPosition.tilt, DELTA);
+ assertEquals("zoom should match", -1, cameraPosition.zoom, DELTA);
+ }
+
+ @Test
+ public void testTypedArrayBuilder() {
+ float bearing = 180;
+ float zoom = 12;
+ float latitude = 10;
+ float longitude = 11;
+ float tilt = 44;
+
+ TypedArray typedArray = mock(TypedArray.class);
+ when(typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraBearing, 0.0f)).thenReturn(bearing);
+ when(typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraTargetLat, 0.0f)).thenReturn(latitude);
+ when(typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraTargetLng, 0.0f)).thenReturn(longitude);
+ when(typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraZoom, 0.0f)).thenReturn(zoom);
+ when(typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraTilt, 0.0f)).thenReturn(tilt);
+ doNothing().when(typedArray).recycle();
+
+ CameraPosition cameraPosition = new CameraPosition.Builder(typedArray).build();
+ assertEquals("bearing should match", bearing, cameraPosition.bearing, DELTA);
+ assertEquals("latlng should match", new LatLng(latitude, longitude), cameraPosition.target);
+ assertEquals("tilt should match", tilt, cameraPosition.tilt, DELTA);
+ assertEquals("zoom should match", zoom, cameraPosition.zoom, DELTA);
+ }
+
+ @Test
+ public void testJniBuilder() {
+ double bearing = 180;
+ double zoom = 12;
+ double latitude = 10;
+ double longitude = 11;
+ double tilt = 44;
+
+ double[] cameraVars = new double[]{latitude, longitude, bearing, tilt, zoom};
+ CameraPosition cameraPosition = new CameraPosition.Builder(cameraVars).build();
+ assertEquals("bearing should match", bearing, cameraPosition.bearing, DELTA);
+ assertEquals("latlng should match", new LatLng(latitude, longitude), cameraPosition.target);
+ assertEquals("tilt should match", tilt, cameraPosition.tilt, DELTA);
+ assertEquals("zoom should match", zoom, cameraPosition.zoom, DELTA);
+ }
+
+ @Test
+ public void testToString() {
+ LatLng latLng = new LatLng(1, 2);
+ CameraPosition cameraPosition = new CameraPosition(latLng, 3, 4, 5);
+ assertEquals("toString should match", "Target: LatLng [latitude=1.0, longitude=2.0, altitude=0.0], Zoom:3.0, "
+ + "Bearing:5.0, Tilt:4.0", cameraPosition.toString());
+ }
+
+ @Test
+ public void testHashcode() {
+ LatLng latLng = new LatLng(1, 2);
+ CameraPosition cameraPosition = new CameraPosition(latLng, 3, 4, 5);
+ assertEquals("hashCode should match", -1007681505, cameraPosition.hashCode());
+ }
+
+ @Test
+ public void testZoomUpdateBuilder() {
+ float zoomLevel = 5;
+ CameraPosition.Builder builder = new CameraPosition.Builder(
+ (CameraUpdateFactory.ZoomUpdate) CameraUpdateFactory.zoomTo(zoomLevel));
+ assertEquals("zoom should match", zoomLevel, builder.build().zoom, 0);
+ }
+
+ @Test
+ public void testEquals() {
+ LatLng latLng = new LatLng(1, 2);
+ CameraPosition cameraPosition = new CameraPosition(latLng, 3, 4, 5);
+ CameraPosition cameraPositionBearing = new CameraPosition(latLng, 3, 4, 9);
+ CameraPosition cameraPositionTilt = new CameraPosition(latLng, 3, 9, 5);
+ CameraPosition cameraPositionZoom = new CameraPosition(latLng, 9, 4, 5);
+ CameraPosition cameraPositionTarget = new CameraPosition(new LatLng(), 3, 4, 5);
+
+ assertEquals("cameraPosition should match itself", cameraPosition, cameraPosition);
+ assertNotEquals("cameraPosition should not match null", null, cameraPosition);
+ assertNotEquals("cameraPosition should not match object", new Object(), cameraPosition);
+ assertNotEquals("cameraPosition should not match for bearing", cameraPositionBearing, cameraPosition);
+ assertNotEquals("cameraPosition should not match for tilt", cameraPositionTilt, cameraPosition);
+ assertNotEquals("cameraPosition should not match for zoom", cameraPositionZoom, cameraPosition);
+ assertNotEquals("cameraPosition should not match for target", cameraPositionTarget, cameraPosition);
+ }
+
+ @Test
+ public void testParcelable() {
+ CameraPosition object = new CameraPosition(new LatLng(1, 2), 3, 4, 5);
+ Parcelable parcelable = MockParcel.obtain(object);
+ assertEquals("Parcel should match original object", parcelable, object);
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/constants/StyleVersionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/constants/StyleVersionTest.java
index 3d9b2a9364..5623afeb58 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/constants/StyleVersionTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/constants/StyleVersionTest.java
@@ -9,13 +9,13 @@ import static junit.framework.Assert.assertEquals;
public class StyleVersionTest {
- private static final double DELTA = 1e-15;
+ private static final double DELTA = 1e-15;
- @Test
- public void testSanity() {
- assertEquals("Style version should match, when upgrading, verify that integers.xml is updated",
- AppConstant.STYLE_VERSION,
- 9,
- DELTA);
- }
+ @Test
+ public void testSanity() {
+ assertEquals("Style version should match, when upgrading, verify that integers.xml is updated",
+ AppConstant.STYLE_VERSION,
+ 9,
+ DELTA);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
index b2cc1e9046..a42ca96cf5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
@@ -20,185 +20,186 @@ import static org.junit.Assert.assertTrue;
public class LatLngBoundsTest {
- private static final double DELTA = 1e-15;
-
- private LatLngBounds mLatLngBounds;
- private static final LatLng LAT_LNG_NULL_ISLAND = new LatLng(0, 0);
- private static final LatLng LAT_LNG_NOT_NULL_ISLAND = new LatLng(2, 2);
-
- @Before
- public void beforeTest() {
- mLatLngBounds = new LatLngBounds.Builder()
- .include(LAT_LNG_NULL_ISLAND)
- .include(LAT_LNG_NOT_NULL_ISLAND)
- .build();
- }
-
- @Test
- public void testSanity() {
- LatLngBounds.Builder latLngBoundsBuilder = new LatLngBounds.Builder();
- latLngBoundsBuilder.include(LAT_LNG_NULL_ISLAND).include(LAT_LNG_NOT_NULL_ISLAND);
- assertNotNull("latLng should not be null", latLngBoundsBuilder.build());
- }
-
- @Test(expected = InvalidLatLngBoundsException.class)
- public void testNoLatLngs() {
- new LatLngBounds.Builder().build();
- }
-
- @Test(expected = InvalidLatLngBoundsException.class)
- public void testOneLatLngs() {
- new LatLngBounds.Builder().include(LAT_LNG_NULL_ISLAND).build();
- }
-
- @Test
- public void testLatitiudeSpan() {
- assertEquals("Span should be the same", 2, mLatLngBounds.getLatitudeSpan(), DELTA);
- }
-
- @Test
- public void testLongitudeSpan() {
- assertEquals("Span should be the same", 2, mLatLngBounds.getLongitudeSpan(), DELTA);
- }
-
- @Test
- public void testCoordinateSpan() {
- LatLngSpan latLngSpan = mLatLngBounds.getSpan();
- assertEquals("LatLngSpan should be the same", new LatLngSpan(2, 2), latLngSpan);
- }
-
- @Test
- public void testCenter() {
- LatLng center = mLatLngBounds.getCenter();
- assertEquals("Center should match", new LatLng(1, 1), center);
- }
-
- @Test
- public void testEmptySpan() {
- mLatLngBounds = new LatLngBounds.Builder()
- .include(LAT_LNG_NOT_NULL_ISLAND)
- .include(LAT_LNG_NOT_NULL_ISLAND)
- .build();
- assertTrue("Should be empty", mLatLngBounds.isEmptySpan());
- }
-
- @Test
- public void testNotEmptySpan() {
- mLatLngBounds = new LatLngBounds.Builder()
- .include(LAT_LNG_NOT_NULL_ISLAND)
- .include(LAT_LNG_NULL_ISLAND)
- .build();
- assertFalse("Should not be empty", mLatLngBounds.isEmptySpan());
- }
-
- @Test
- public void testToLatLngs() {
- mLatLngBounds = new LatLngBounds.Builder()
- .include(LAT_LNG_NOT_NULL_ISLAND)
- .include(LAT_LNG_NULL_ISLAND)
- .build();
-
- assertArrayEquals("LatLngs should match",
- new LatLng[]{LAT_LNG_NOT_NULL_ISLAND, LAT_LNG_NULL_ISLAND},
- mLatLngBounds.toLatLngs());
- }
-
- @Test
- public void testIncluding() {
- assertTrue("LatLng should be included", mLatLngBounds.contains(new LatLng(1, 1)));
- }
-
- @Test
- public void testIncludes() {
- List<LatLng> points = new ArrayList<>();
- points.add(LAT_LNG_NULL_ISLAND);
- points.add(LAT_LNG_NOT_NULL_ISLAND);
-
- LatLngBounds latLngBounds1 = new LatLngBounds.Builder()
- .includes(points)
- .build();
-
- LatLngBounds latLngBounds2 = new LatLngBounds.Builder()
- .include(LAT_LNG_NULL_ISLAND)
- .include(LAT_LNG_NOT_NULL_ISLAND)
- .build();
-
- assertEquals("LatLngBounds should match", latLngBounds1, latLngBounds2);
- }
-
- @Test
- public void testNoIncluding() {
- assertFalse("LatLng should not be included", mLatLngBounds.contains(new LatLng(3, 1)));
- }
-
- @Test
- public void testHashCode() {
- assertEquals(2147483647, mLatLngBounds.hashCode(), -1946419200);
- }
-
- @Test
- public void testEquality() {
- LatLngBounds latLngBounds = new LatLngBounds.Builder()
- .include(LAT_LNG_NULL_ISLAND)
- .include(LAT_LNG_NOT_NULL_ISLAND)
- .build();
- assertEquals("equality should match", mLatLngBounds, latLngBounds);
- assertEquals("not equal to a different object type", mLatLngBounds.equals(LAT_LNG_NOT_NULL_ISLAND), false);
- }
-
- @Test
- public void testToString() {
- assertEquals(mLatLngBounds.toString(), "N:2.0; E:2.0; S:0.0; W:0.0");
- }
-
- @Test
- public void testIntersect() {
- LatLngBounds latLngBounds = new LatLngBounds.Builder()
- .include(new LatLng(1, 1))
- .include(LAT_LNG_NULL_ISLAND)
- .build();
- assertEquals("intersect should match", latLngBounds, latLngBounds.intersect(mLatLngBounds.getLatNorth(), mLatLngBounds.getLonEast(), mLatLngBounds.getLatSouth(), mLatLngBounds.getLonWest()));
- }
-
- @Test
- public void testNoIntersect() {
- LatLngBounds latLngBounds = new LatLngBounds.Builder()
- .include(new LatLng(10, 10))
- .include(new LatLng(9, 8))
- .build();
- assertNull(latLngBounds.intersect(mLatLngBounds));
- }
-
- @Test
- public void testInnerUnion() {
- LatLngBounds latLngBounds = new LatLngBounds.Builder()
- .include(new LatLng(1, 1))
- .include(LAT_LNG_NULL_ISLAND)
- .build();
- assertEquals("union should match", latLngBounds, latLngBounds.intersect(mLatLngBounds));
- }
-
- @Test
- public void testOuterUnion() {
- LatLngBounds latLngBounds = new LatLngBounds.Builder()
- .include(new LatLng(10, 10))
- .include(new LatLng(9, 8))
- .build();
- assertEquals("outer union should match",
- latLngBounds.union(mLatLngBounds),
- new LatLngBounds.Builder()
- .include(new LatLng(10, 10))
- .include(LAT_LNG_NULL_ISLAND)
- .build());
- }
-
- @Test
- public void testParcelable() {
- LatLngBounds latLngBounds = new LatLngBounds.Builder()
- .include(new LatLng(10, 10))
- .include(new LatLng(9, 8))
- .build();
- Parcelable parcel = MockParcel.obtain(latLngBounds);
- assertEquals("Parcel should match original object", parcel, latLngBounds);
- }
+ private static final double DELTA = 1e-15;
+
+ private LatLngBounds latLngBounds;
+ private static final LatLng LAT_LNG_NULL_ISLAND = new LatLng(0, 0);
+ private static final LatLng LAT_LNG_NOT_NULL_ISLAND = new LatLng(2, 2);
+
+ @Before
+ public void beforeTest() {
+ latLngBounds = new LatLngBounds.Builder()
+ .include(LAT_LNG_NULL_ISLAND)
+ .include(LAT_LNG_NOT_NULL_ISLAND)
+ .build();
+ }
+
+ @Test
+ public void testSanity() {
+ LatLngBounds.Builder latLngBoundsBuilder = new LatLngBounds.Builder();
+ latLngBoundsBuilder.include(LAT_LNG_NULL_ISLAND).include(LAT_LNG_NOT_NULL_ISLAND);
+ assertNotNull("latLng should not be null", latLngBoundsBuilder.build());
+ }
+
+ @Test(expected = InvalidLatLngBoundsException.class)
+ public void testNoLatLngs() {
+ new LatLngBounds.Builder().build();
+ }
+
+ @Test(expected = InvalidLatLngBoundsException.class)
+ public void testOneLatLngs() {
+ new LatLngBounds.Builder().include(LAT_LNG_NULL_ISLAND).build();
+ }
+
+ @Test
+ public void testLatitiudeSpan() {
+ assertEquals("Span should be the same", 2, latLngBounds.getLatitudeSpan(), DELTA);
+ }
+
+ @Test
+ public void testLongitudeSpan() {
+ assertEquals("Span should be the same", 2, latLngBounds.getLongitudeSpan(), DELTA);
+ }
+
+ @Test
+ public void testCoordinateSpan() {
+ LatLngSpan latLngSpan = latLngBounds.getSpan();
+ assertEquals("LatLngSpan should be the same", new LatLngSpan(2, 2), latLngSpan);
+ }
+
+ @Test
+ public void testCenter() {
+ LatLng center = latLngBounds.getCenter();
+ assertEquals("Center should match", new LatLng(1, 1), center);
+ }
+
+ @Test
+ public void testEmptySpan() {
+ latLngBounds = new LatLngBounds.Builder()
+ .include(LAT_LNG_NOT_NULL_ISLAND)
+ .include(LAT_LNG_NOT_NULL_ISLAND)
+ .build();
+ assertTrue("Should be empty", latLngBounds.isEmptySpan());
+ }
+
+ @Test
+ public void testNotEmptySpan() {
+ latLngBounds = new LatLngBounds.Builder()
+ .include(LAT_LNG_NOT_NULL_ISLAND)
+ .include(LAT_LNG_NULL_ISLAND)
+ .build();
+ assertFalse("Should not be empty", latLngBounds.isEmptySpan());
+ }
+
+ @Test
+ public void testToLatLngs() {
+ latLngBounds = new LatLngBounds.Builder()
+ .include(LAT_LNG_NOT_NULL_ISLAND)
+ .include(LAT_LNG_NULL_ISLAND)
+ .build();
+
+ assertArrayEquals("LatLngs should match",
+ new LatLng[] {LAT_LNG_NOT_NULL_ISLAND, LAT_LNG_NULL_ISLAND},
+ latLngBounds.toLatLngs());
+ }
+
+ @Test
+ public void testIncluding() {
+ assertTrue("LatLng should be included", latLngBounds.contains(new LatLng(1, 1)));
+ }
+
+ @Test
+ public void testIncludes() {
+ List<LatLng> points = new ArrayList<>();
+ points.add(LAT_LNG_NULL_ISLAND);
+ points.add(LAT_LNG_NOT_NULL_ISLAND);
+
+ LatLngBounds latLngBounds1 = new LatLngBounds.Builder()
+ .includes(points)
+ .build();
+
+ LatLngBounds latLngBounds2 = new LatLngBounds.Builder()
+ .include(LAT_LNG_NULL_ISLAND)
+ .include(LAT_LNG_NOT_NULL_ISLAND)
+ .build();
+
+ assertEquals("LatLngBounds should match", latLngBounds1, latLngBounds2);
+ }
+
+ @Test
+ public void testNoIncluding() {
+ assertFalse("LatLng should not be included", latLngBounds.contains(new LatLng(3, 1)));
+ }
+
+ @Test
+ public void testHashCode() {
+ assertEquals(2147483647, latLngBounds.hashCode(), -1946419200);
+ }
+
+ @Test
+ public void testEquality() {
+ LatLngBounds latLngBounds = new LatLngBounds.Builder()
+ .include(LAT_LNG_NULL_ISLAND)
+ .include(LAT_LNG_NOT_NULL_ISLAND)
+ .build();
+ assertEquals("equality should match", this.latLngBounds, latLngBounds);
+ assertEquals("not equal to a different object type", this.latLngBounds.equals(LAT_LNG_NOT_NULL_ISLAND), false);
+ }
+
+ @Test
+ public void testToString() {
+ assertEquals(latLngBounds.toString(), "N:2.0; E:2.0; S:0.0; W:0.0");
+ }
+
+ @Test
+ public void testIntersect() {
+ LatLngBounds latLngBounds = new LatLngBounds.Builder()
+ .include(new LatLng(1, 1))
+ .include(LAT_LNG_NULL_ISLAND)
+ .build();
+ assertEquals("intersect should match", latLngBounds, latLngBounds.intersect(this.latLngBounds.getLatNorth(),
+ this.latLngBounds.getLonEast(), this.latLngBounds.getLatSouth(), this.latLngBounds.getLonWest()));
+ }
+
+ @Test
+ public void testNoIntersect() {
+ LatLngBounds latLngBounds = new LatLngBounds.Builder()
+ .include(new LatLng(10, 10))
+ .include(new LatLng(9, 8))
+ .build();
+ assertNull(latLngBounds.intersect(this.latLngBounds));
+ }
+
+ @Test
+ public void testInnerUnion() {
+ LatLngBounds latLngBounds = new LatLngBounds.Builder()
+ .include(new LatLng(1, 1))
+ .include(LAT_LNG_NULL_ISLAND)
+ .build();
+ assertEquals("union should match", latLngBounds, latLngBounds.intersect(this.latLngBounds));
+ }
+
+ @Test
+ public void testOuterUnion() {
+ LatLngBounds latLngBounds = new LatLngBounds.Builder()
+ .include(new LatLng(10, 10))
+ .include(new LatLng(9, 8))
+ .build();
+ assertEquals("outer union should match",
+ latLngBounds.union(this.latLngBounds),
+ new LatLngBounds.Builder()
+ .include(new LatLng(10, 10))
+ .include(LAT_LNG_NULL_ISLAND)
+ .build());
+ }
+
+ @Test
+ public void testParcelable() {
+ LatLngBounds latLngBounds = new LatLngBounds.Builder()
+ .include(new LatLng(10, 10))
+ .include(new LatLng(9, 8))
+ .build();
+ Parcelable parcel = MockParcel.obtain(latLngBounds);
+ assertEquals("Parcel should match original object", parcel, latLngBounds);
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngSpanTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngSpanTest.java
index e184097a43..12297247cf 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngSpanTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngSpanTest.java
@@ -11,55 +11,55 @@ import static org.junit.Assert.assertNotNull;
public class LatLngSpanTest {
- private static final double DELTA = 1e-15;
- private static final LatLng LAT_LNG_NULL_ISLAND = new LatLng(0, 0);
+ private static final double DELTA = 1e-15;
+ private static final LatLng LAT_LNG_NULL_ISLAND = new LatLng(0, 0);
- @Test
- public void testSanity() {
- LatLngSpan latLngSpan = new LatLngSpan(0.0, 0.0);
- assertNotNull("latLngSpan should not be null", latLngSpan);
- }
+ @Test
+ public void testSanity() {
+ LatLngSpan latLngSpan = new LatLngSpan(0.0, 0.0);
+ assertNotNull("latLngSpan should not be null", latLngSpan);
+ }
- @Test
- public void testEquality() {
- LatLngSpan latLngSpan = new LatLngSpan(0.0, 0.0);
- assertEquals("latLngSpan is not equal to a LatLng", latLngSpan.equals(LAT_LNG_NULL_ISLAND), false);
- }
+ @Test
+ public void testEquality() {
+ LatLngSpan latLngSpan = new LatLngSpan(0.0, 0.0);
+ assertEquals("latLngSpan is not equal to a LatLng", latLngSpan.equals(LAT_LNG_NULL_ISLAND), false);
+ }
- @Test
- public void testLatitudeConstructor() {
- double latitude = 1.23;
- LatLngSpan latLngSpan = new LatLngSpan(latitude, 0.0);
- assertEquals("latitude in constructor", latLngSpan.getLatitudeSpan(), latitude, DELTA);
- }
+ @Test
+ public void testLatitudeConstructor() {
+ double latitude = 1.23;
+ LatLngSpan latLngSpan = new LatLngSpan(latitude, 0.0);
+ assertEquals("latitude in constructor", latLngSpan.getLatitudeSpan(), latitude, DELTA);
+ }
- @Test
- public void testLongitudeConstructor() {
- double longitude = 1.23;
- LatLngSpan latLngSpan = new LatLngSpan(0.0, longitude);
- assertEquals("latitude in constructor", latLngSpan.getLongitudeSpan(), longitude, DELTA);
- }
+ @Test
+ public void testLongitudeConstructor() {
+ double longitude = 1.23;
+ LatLngSpan latLngSpan = new LatLngSpan(0.0, longitude);
+ assertEquals("latitude in constructor", latLngSpan.getLongitudeSpan(), longitude, DELTA);
+ }
- @Test
- public void testLatitudeMethod() {
- double latitude = 1.23;
- LatLngSpan latLngSpan = new LatLngSpan(0.0, 0.0);
- latLngSpan.setLatitudeSpan(latitude);
- assertEquals("latitude in constructor", latLngSpan.getLatitudeSpan(), latitude, DELTA);
- }
+ @Test
+ public void testLatitudeMethod() {
+ double latitude = 1.23;
+ LatLngSpan latLngSpan = new LatLngSpan(0.0, 0.0);
+ latLngSpan.setLatitudeSpan(latitude);
+ assertEquals("latitude in constructor", latLngSpan.getLatitudeSpan(), latitude, DELTA);
+ }
- @Test
- public void testLongitudeMethod() {
- double longitude = 1.23;
- LatLngSpan latLngSpan = new LatLngSpan(0.0, 0.0);
- latLngSpan.setLongitudeSpan(longitude);
- assertEquals("latitude in constructor", latLngSpan.getLongitudeSpan(), longitude, DELTA);
- }
+ @Test
+ public void testLongitudeMethod() {
+ double longitude = 1.23;
+ LatLngSpan latLngSpan = new LatLngSpan(0.0, 0.0);
+ latLngSpan.setLongitudeSpan(longitude);
+ assertEquals("latitude in constructor", latLngSpan.getLongitudeSpan(), longitude, DELTA);
+ }
- @Test
- public void testParcelable() {
- LatLngSpan object = new LatLngSpan(1, 2);
- Parcelable parcel = MockParcel.obtain(object);
- assertEquals("parcel should match initial object", object, parcel);
- }
+ @Test
+ public void testParcelable() {
+ LatLngSpan object = new LatLngSpan(1, 2);
+ Parcelable parcel = MockParcel.obtain(object);
+ assertEquals("parcel should match initial object", object, parcel);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java
index de5dbc5e09..5cbf1fa63c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java
@@ -16,182 +16,182 @@ import static org.mockito.Mockito.when;
public class LatLngTest {
- private static final double DELTA = 1e-15;
-
- @Test
- public void testSanity() {
- LatLng latLng = new LatLng(0.0, 0.0);
- assertNotNull("latLng should not be null", latLng);
- }
-
- @Test
- public void testLatitudeEmptyConstructor() {
- LatLng latLng = new LatLng();
- assertEquals("latitude default value", latLng.getLatitude(), 0, DELTA);
- }
-
- @Test
- public void testLongitudeEmptyConstructor() {
- LatLng latLng = new LatLng();
- assertEquals("longitude default value", latLng.getLongitude(), 0, DELTA);
- }
-
- @Test
- public void testAltitudeEmptyConstructor() {
- LatLng latLng1 = new LatLng();
- assertEquals("altitude default value", latLng1.getAltitude(), 0.0, DELTA);
- }
-
- @Test
- public void testLatitudeConstructor() {
- double latitude = 1.2;
- LatLng latLng = new LatLng(latitude, 3.4);
- assertEquals("latitude should match", latLng.getLatitude(), latitude, DELTA);
- }
-
- @Test
- public void testLongitudeConstructor() {
- double longitude = 3.4;
- LatLng latLng = new LatLng(1.2, longitude);
- assertEquals("longitude should match", latLng.getLongitude(), longitude, DELTA);
- }
-
- @Test
- public void testAltitudeConstructor() {
- LatLng latLng1 = new LatLng(1.2, 3.4);
- assertEquals("altitude default value", latLng1.getAltitude(), 0.0, DELTA);
-
- double altitude = 5.6;
- LatLng latLng2 = new LatLng(1.2, 3.4, altitude);
- assertEquals("altitude default value", latLng2.getAltitude(), altitude, DELTA);
- }
-
- @Test
- public void testLatitudeSetter() {
- LatLng latLng = new LatLng(1.2, 3.4);
- latLng.setLatitude(3);
- assertEquals("latitude should match", 3, latLng.getLatitude(), DELTA);
- }
-
- @Test
- public void testLongitudeSetter() {
- LatLng latLng = new LatLng(1.2, 3.4);
- latLng.setLongitude(3);
- assertEquals("longitude should match", 3, latLng.getLongitude(), DELTA);
- }
-
- @Test
- public void testAltitudeSetter() {
- LatLng latLng = new LatLng(1.2, 3.4);
- latLng.setAltitude(3);
- assertEquals("altitude should match", 3, latLng.getAltitude(), DELTA);
- }
-
- @Test
- public void testLatLngConstructor() {
- LatLng latLng1 = new LatLng(1.2, 3.4);
- LatLng latLng2 = new LatLng(latLng1);
- assertEquals("latLng should match", latLng1, latLng2);
- }
-
- @Test
- public void testDistanceTo() {
- LatLng latLng1 = new LatLng(0.0, 0.0);
- LatLng latLng2 = new LatLng(1.0, 1.0);
- assertEquals("distances should match",
- latLng1.distanceTo(latLng2),
- 157425.53710839353, DELTA);
- }
-
- @Test
- public void testDistanceToSamePoint() {
- LatLng latLng1 = new LatLng(40.71199035644531, -74.0081);
- LatLng latLng2 = new LatLng(40.71199035644531, -74.0081);
- double distance = latLng1.distanceTo(latLng2);
- assertEquals("distance should match", 0.0, distance, DELTA);
- }
-
- @Test
- public void testLocationProvider() {
- double latitude = 1.2;
- double longitude = 3.4;
- double altitude = 5.6;
-
- // Mock the location class
- Location locationMocked = mock(Location.class);
- when(locationMocked.getLatitude()).thenReturn(latitude);
- when(locationMocked.getLongitude()).thenReturn(longitude);
- when(locationMocked.getAltitude()).thenReturn(altitude);
-
- // Test the constructor
- LatLng latLng = new LatLng(locationMocked);
- assertEquals("latitude should match", latLng.getLatitude(), latitude, DELTA);
- assertEquals("longitude should match", latLng.getLongitude(), longitude, DELTA);
- assertEquals("altitude should match", latLng.getAltitude(), altitude, DELTA);
- }
-
- @Test
- public void testHashCode() {
- double latitude = 1.2;
- double longitude = 3.4;
- double altitude = 5.6;
- LatLng latLng = new LatLng(latitude, longitude, altitude);
- assertEquals("hash code should match", latLng.hashCode(), -151519232);
- }
-
- @Test
- public void testToString() {
- double latitude = 1.2;
- double longitude = 3.4;
- double altitude = 5.6;
- LatLng latLng = new LatLng(latitude, longitude, altitude);
- assertEquals("string should match",
- latLng.toString(),
- "LatLng [latitude=1.2, longitude=3.4, altitude=5.6]");
- }
-
- @Test
- public void testEqualsOther() {
- double latitude = 1.2;
- double longitude = 3.4;
- double altitude = 5.6;
- LatLng latLng1 = new LatLng(latitude, longitude, altitude);
- LatLng latLng2 = new LatLng(latitude, longitude, altitude);
- assertEquals("LatLng should match", latLng1, latLng2);
- }
-
- @Test
- public void testEqualsItself() {
- LatLng latLng = new LatLng(1, 2, 3);
- assertEquals("LatLng should match", latLng, latLng);
- }
-
- @Test
- public void testNotEquals() {
- LatLng latLng = new LatLng(1, 2);
- assertNotEquals("LatLng should match", latLng, new Object());
- }
-
- @Test
- public void testParcelable() {
- LatLng latLng = new LatLng(45.0, -185.0);
- Parcelable parcel = MockParcel.obtain(latLng);
- assertEquals("parcel should match initial object", latLng, parcel);
- }
-
- @Test
- public void testWrapped() {
- LatLng latLng = new LatLng(45.0, -185.0);
- LatLng wrapped = latLng.wrap();
- assertNotSame(latLng, wrapped);
- assertEquals("longitude wrapped value", wrapped.getLongitude(), 175.0, DELTA);
- }
-
- @Test
- public void testUnnecessaryWrapped() {
- LatLng latLng = new LatLng(45.0, 50.0);
- LatLng wrapped = latLng.wrap();
- assertNotSame(latLng, wrapped);
- assertEquals("longitude wrapped value", wrapped.getLongitude(), 50.0, DELTA);
- }
+ private static final double DELTA = 1e-15;
+
+ @Test
+ public void testSanity() {
+ LatLng latLng = new LatLng(0.0, 0.0);
+ assertNotNull("latLng should not be null", latLng);
+ }
+
+ @Test
+ public void testLatitudeEmptyConstructor() {
+ LatLng latLng = new LatLng();
+ assertEquals("latitude default value", latLng.getLatitude(), 0, DELTA);
+ }
+
+ @Test
+ public void testLongitudeEmptyConstructor() {
+ LatLng latLng = new LatLng();
+ assertEquals("longitude default value", latLng.getLongitude(), 0, DELTA);
+ }
+
+ @Test
+ public void testAltitudeEmptyConstructor() {
+ LatLng latLng1 = new LatLng();
+ assertEquals("altitude default value", latLng1.getAltitude(), 0.0, DELTA);
+ }
+
+ @Test
+ public void testLatitudeConstructor() {
+ double latitude = 1.2;
+ LatLng latLng = new LatLng(latitude, 3.4);
+ assertEquals("latitude should match", latLng.getLatitude(), latitude, DELTA);
+ }
+
+ @Test
+ public void testLongitudeConstructor() {
+ double longitude = 3.4;
+ LatLng latLng = new LatLng(1.2, longitude);
+ assertEquals("longitude should match", latLng.getLongitude(), longitude, DELTA);
+ }
+
+ @Test
+ public void testAltitudeConstructor() {
+ LatLng latLng1 = new LatLng(1.2, 3.4);
+ assertEquals("altitude default value", latLng1.getAltitude(), 0.0, DELTA);
+
+ double altitude = 5.6;
+ LatLng latLng2 = new LatLng(1.2, 3.4, altitude);
+ assertEquals("altitude default value", latLng2.getAltitude(), altitude, DELTA);
+ }
+
+ @Test
+ public void testLatitudeSetter() {
+ LatLng latLng = new LatLng(1.2, 3.4);
+ latLng.setLatitude(3);
+ assertEquals("latitude should match", 3, latLng.getLatitude(), DELTA);
+ }
+
+ @Test
+ public void testLongitudeSetter() {
+ LatLng latLng = new LatLng(1.2, 3.4);
+ latLng.setLongitude(3);
+ assertEquals("longitude should match", 3, latLng.getLongitude(), DELTA);
+ }
+
+ @Test
+ public void testAltitudeSetter() {
+ LatLng latLng = new LatLng(1.2, 3.4);
+ latLng.setAltitude(3);
+ assertEquals("altitude should match", 3, latLng.getAltitude(), DELTA);
+ }
+
+ @Test
+ public void testLatLngConstructor() {
+ LatLng latLng1 = new LatLng(1.2, 3.4);
+ LatLng latLng2 = new LatLng(latLng1);
+ assertEquals("latLng should match", latLng1, latLng2);
+ }
+
+ @Test
+ public void testDistanceTo() {
+ LatLng latLng1 = new LatLng(0.0, 0.0);
+ LatLng latLng2 = new LatLng(1.0, 1.0);
+ assertEquals("distances should match",
+ latLng1.distanceTo(latLng2),
+ 157425.53710839353, DELTA);
+ }
+
+ @Test
+ public void testDistanceToSamePoint() {
+ LatLng latLng1 = new LatLng(40.71199035644531, -74.0081);
+ LatLng latLng2 = new LatLng(40.71199035644531, -74.0081);
+ double distance = latLng1.distanceTo(latLng2);
+ assertEquals("distance should match", 0.0, distance, DELTA);
+ }
+
+ @Test
+ public void testLocationProvider() {
+ double latitude = 1.2;
+ double longitude = 3.4;
+ double altitude = 5.6;
+
+ // Mock the location class
+ Location locationMocked = mock(Location.class);
+ when(locationMocked.getLatitude()).thenReturn(latitude);
+ when(locationMocked.getLongitude()).thenReturn(longitude);
+ when(locationMocked.getAltitude()).thenReturn(altitude);
+
+ // Test the constructor
+ LatLng latLng = new LatLng(locationMocked);
+ assertEquals("latitude should match", latLng.getLatitude(), latitude, DELTA);
+ assertEquals("longitude should match", latLng.getLongitude(), longitude, DELTA);
+ assertEquals("altitude should match", latLng.getAltitude(), altitude, DELTA);
+ }
+
+ @Test
+ public void testHashCode() {
+ double latitude = 1.2;
+ double longitude = 3.4;
+ double altitude = 5.6;
+ LatLng latLng = new LatLng(latitude, longitude, altitude);
+ assertEquals("hash code should match", latLng.hashCode(), -151519232);
+ }
+
+ @Test
+ public void testToString() {
+ double latitude = 1.2;
+ double longitude = 3.4;
+ double altitude = 5.6;
+ LatLng latLng = new LatLng(latitude, longitude, altitude);
+ assertEquals("string should match",
+ latLng.toString(),
+ "LatLng [latitude=1.2, longitude=3.4, altitude=5.6]");
+ }
+
+ @Test
+ public void testEqualsOther() {
+ double latitude = 1.2;
+ double longitude = 3.4;
+ double altitude = 5.6;
+ LatLng latLng1 = new LatLng(latitude, longitude, altitude);
+ LatLng latLng2 = new LatLng(latitude, longitude, altitude);
+ assertEquals("LatLng should match", latLng1, latLng2);
+ }
+
+ @Test
+ public void testEqualsItself() {
+ LatLng latLng = new LatLng(1, 2, 3);
+ assertEquals("LatLng should match", latLng, latLng);
+ }
+
+ @Test
+ public void testNotEquals() {
+ LatLng latLng = new LatLng(1, 2);
+ assertNotEquals("LatLng should match", latLng, new Object());
+ }
+
+ @Test
+ public void testParcelable() {
+ LatLng latLng = new LatLng(45.0, -185.0);
+ Parcelable parcel = MockParcel.obtain(latLng);
+ assertEquals("parcel should match initial object", latLng, parcel);
+ }
+
+ @Test
+ public void testWrapped() {
+ LatLng latLng = new LatLng(45.0, -185.0);
+ LatLng wrapped = latLng.wrap();
+ assertNotSame(latLng, wrapped);
+ assertEquals("longitude wrapped value", wrapped.getLongitude(), 175.0, DELTA);
+ }
+
+ @Test
+ public void testUnnecessaryWrapped() {
+ LatLng latLng = new LatLng(45.0, 50.0);
+ LatLng wrapped = latLng.wrap();
+ assertNotSame(latLng, wrapped);
+ assertEquals("longitude wrapped value", wrapped.getLongitude(), 50.0, DELTA);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/ProjectedMetersTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/ProjectedMetersTest.java
index 5525684601..00fd125a1a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/ProjectedMetersTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/ProjectedMetersTest.java
@@ -11,56 +11,56 @@ import static org.junit.Assert.assertNotNull;
public class ProjectedMetersTest {
- private static final LatLng LAT_LNG_NULL_ISLAND = new LatLng(0, 0);
+ private static final LatLng LAT_LNG_NULL_ISLAND = new LatLng(0, 0);
- @Test
- public void testSanity() {
- ProjectedMeters projectedMeters = new ProjectedMeters(0.0, 0.0);
- assertNotNull("projectedMeters should not be null", projectedMeters);
- }
+ @Test
+ public void testSanity() {
+ ProjectedMeters projectedMeters = new ProjectedMeters(0.0, 0.0);
+ assertNotNull("projectedMeters should not be null", projectedMeters);
+ }
- @Test
- public void testEquality() {
- ProjectedMeters projectedMeters = new ProjectedMeters(0.0, 0.0);
- assertEquals("projectedMeters is not equal to a LatLng", projectedMeters.equals(LAT_LNG_NULL_ISLAND), false);
- assertEquals("projectedMeters is equal to itself", projectedMeters.equals(projectedMeters), true);
- }
+ @Test
+ public void testEquality() {
+ ProjectedMeters projectedMeters = new ProjectedMeters(0.0, 0.0);
+ assertEquals("projectedMeters is not equal to a LatLng", projectedMeters.equals(LAT_LNG_NULL_ISLAND), false);
+ assertEquals("projectedMeters is equal to itself", projectedMeters.equals(projectedMeters), true);
+ }
- @Test
- public void testNorthing() {
- ProjectedMeters projectedMeters = new ProjectedMeters(1.0, 0.0);
- assertEquals("northing should be 1", 1, projectedMeters.getNorthing(), 0);
- }
+ @Test
+ public void testNorthing() {
+ ProjectedMeters projectedMeters = new ProjectedMeters(1.0, 0.0);
+ assertEquals("northing should be 1", 1, projectedMeters.getNorthing(), 0);
+ }
- @Test
- public void testEasting() {
- ProjectedMeters projectedMeters = new ProjectedMeters(0.0, 1.0);
- assertEquals("easting should be 1", 1, projectedMeters.getEasting(), 0);
- }
+ @Test
+ public void testEasting() {
+ ProjectedMeters projectedMeters = new ProjectedMeters(0.0, 1.0);
+ assertEquals("easting should be 1", 1, projectedMeters.getEasting(), 0);
+ }
- @Test
- public void testConstructor() {
- ProjectedMeters projectedMeters1 = new ProjectedMeters(1, 2);
- ProjectedMeters projectedMeters2 = new ProjectedMeters(projectedMeters1);
- assertEquals("projectedmeters should match", projectedMeters1, projectedMeters2);
- }
+ @Test
+ public void testConstructor() {
+ ProjectedMeters projectedMeters1 = new ProjectedMeters(1, 2);
+ ProjectedMeters projectedMeters2 = new ProjectedMeters(projectedMeters1);
+ assertEquals("projectedmeters should match", projectedMeters1, projectedMeters2);
+ }
- @Test
- public void testHashcode() {
- ProjectedMeters meters = new ProjectedMeters(1, 2);
- assertEquals("hashcode should match", -1048576, meters.hashCode());
- }
+ @Test
+ public void testHashcode() {
+ ProjectedMeters meters = new ProjectedMeters(1, 2);
+ assertEquals("hashcode should match", -1048576, meters.hashCode());
+ }
- @Test
- public void testToString() {
- ProjectedMeters meters = new ProjectedMeters(1, 1);
- assertEquals("toString should match", "ProjectedMeters [northing=1.0, easting=1.0]", meters.toString());
- }
+ @Test
+ public void testToString() {
+ ProjectedMeters meters = new ProjectedMeters(1, 1);
+ assertEquals("toString should match", "ProjectedMeters [northing=1.0, easting=1.0]", meters.toString());
+ }
- @Test
- public void testParcelable() {
- ProjectedMeters meters = new ProjectedMeters(1, 1);
- Parcelable parcel = MockParcel.obtain(meters);
- assertEquals("parcel should match initial object", meters, parcel);
- }
+ @Test
+ public void testParcelable() {
+ ProjectedMeters meters = new ProjectedMeters(1, 1);
+ Parcelable parcel = MockParcel.obtain(meters);
+ assertEquals("parcel should match initial object", meters, parcel);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java
index cad268c2ba..12b779de5d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java
@@ -11,84 +11,85 @@ import static org.junit.Assert.assertNotNull;
public class VisibleRegionTest {
- private static final LatLng FAR_LEFT = new LatLng(52, -12);
- private static final LatLng NEAR_LEFT = new LatLng(34, -12);
- private static final LatLng FAR_RIGHT = new LatLng(52, 26);
- private static final LatLng NEAR_RIGHT = new LatLng(34, 26);
- private static final LatLngBounds BOUNDS = new LatLngBounds.Builder().include(FAR_LEFT).include(FAR_RIGHT).include(NEAR_LEFT).include(NEAR_RIGHT).build();
-
- @Test
- public void testSanity() {
- VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
- assertNotNull("region should not be null", region);
- }
-
- @Test
- public void testEquality() {
- VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
- assertEquals("visibleRegion is not equal to a LatLng", region.equals(FAR_LEFT), false);
- assertEquals("visibleRegion is equal to itself", region.equals(region), true);
- }
-
- @Test
- public void testFarLeftConstructor() {
- VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
- assertEquals("LatLng should match", region.farLeft, FAR_LEFT);
- }
-
- @Test
- public void testNearLeftConstructor() {
- VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
- assertEquals("LatLng should match", region.nearLeft, NEAR_LEFT);
- }
-
- @Test
- public void testFarRightConstructor() {
- VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
- assertEquals("LatLng should match", region.farRight, FAR_RIGHT);
- }
-
- @Test
- public void testNearRightConstructor() {
- VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
- assertEquals("LatLng should match", region.nearRight, NEAR_RIGHT);
- }
-
- @Test
- public void testLatLngBoundsConstructor() {
- VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
- assertEquals("LatLngBounds should match", region.latLngBounds, BOUNDS);
- }
-
- @Test
- public void testEquals() {
- VisibleRegion regionLeft = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
- VisibleRegion regionRight = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
- assertEquals("VisibleRegions should match", regionLeft, regionRight);
- }
-
- @Test
- public void testHashcode() {
- VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
- assertEquals("hashcode should match", -923534102, region.hashCode());
- }
-
- @Test
- public void testToString() {
- VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
- assertEquals("string should match",
- "[farLeft [LatLng [latitude=52.0, longitude=-12.0, altitude=0.0]], " +
- "farRight [LatLng [latitude=52.0, longitude=26.0, altitude=0.0]], " +
- "nearLeft [LatLng [latitude=34.0, longitude=-12.0, altitude=0.0]], " +
- "nearRight [LatLng [latitude=34.0, longitude=26.0, altitude=0.0]], " +
- "latLngBounds [N:52.0; E:26.0; S:34.0; W:-12.0]]"
- , region.toString());
- }
-
- @Test
- public void testParcelable() {
- VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
- Parcelable parcel = MockParcel.obtain(region);
- assertEquals("parcel should match initial object", region, parcel);
- }
+ private static final LatLng FAR_LEFT = new LatLng(52, -12);
+ private static final LatLng NEAR_LEFT = new LatLng(34, -12);
+ private static final LatLng FAR_RIGHT = new LatLng(52, 26);
+ private static final LatLng NEAR_RIGHT = new LatLng(34, 26);
+ private static final LatLngBounds BOUNDS =
+ new LatLngBounds.Builder().include(FAR_LEFT).include(FAR_RIGHT).include(NEAR_LEFT).include(NEAR_RIGHT).build();
+
+ @Test
+ public void testSanity() {
+ VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ assertNotNull("region should not be null", region);
+ }
+
+ @Test
+ public void testEquality() {
+ VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ assertEquals("visibleRegion is not equal to a LatLng", region.equals(FAR_LEFT), false);
+ assertEquals("visibleRegion is equal to itself", region.equals(region), true);
+ }
+
+ @Test
+ public void testFarLeftConstructor() {
+ VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ assertEquals("LatLng should match", region.farLeft, FAR_LEFT);
+ }
+
+ @Test
+ public void testNearLeftConstructor() {
+ VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ assertEquals("LatLng should match", region.nearLeft, NEAR_LEFT);
+ }
+
+ @Test
+ public void testFarRightConstructor() {
+ VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ assertEquals("LatLng should match", region.farRight, FAR_RIGHT);
+ }
+
+ @Test
+ public void testNearRightConstructor() {
+ VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ assertEquals("LatLng should match", region.nearRight, NEAR_RIGHT);
+ }
+
+ @Test
+ public void testLatLngBoundsConstructor() {
+ VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ assertEquals("LatLngBounds should match", region.latLngBounds, BOUNDS);
+ }
+
+ @Test
+ public void testEquals() {
+ VisibleRegion regionLeft = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ VisibleRegion regionRight = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ assertEquals("VisibleRegions should match", regionLeft, regionRight);
+ }
+
+ @Test
+ public void testHashcode() {
+ VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ assertEquals("hashcode should match", -923534102, region.hashCode());
+ }
+
+ @Test
+ public void testToString() {
+ VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ assertEquals("string should match",
+ "[farLeft [LatLng [latitude=52.0, longitude=-12.0, altitude=0.0]], "
+ + "farRight [LatLng [latitude=52.0, longitude=26.0, altitude=0.0]], "
+ + "nearLeft [LatLng [latitude=34.0, longitude=-12.0, altitude=0.0]], "
+ + "nearRight [LatLng [latitude=34.0, longitude=26.0, altitude=0.0]], "
+ + "latLngBounds [N:52.0; E:26.0; S:34.0; W:-12.0]]",
+ region.toString());
+ }
+
+ @Test
+ public void testParcelable() {
+ VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ Parcelable parcel = MockParcel.obtain(region);
+ assertEquals("parcel should match initial object", region, parcel);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java
index dbde9a4420..ce0cb00b0b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java
@@ -7,7 +7,6 @@ import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.utils.MockParcel;
import org.junit.Test;
@@ -22,174 +21,170 @@ import static org.junit.Assert.assertTrue;
public class MapboxMapOptionsTest {
- @Test
- public void testSanity() {
- assertNotNull("should not be null", new MapboxMapOptions());
- }
-
- @Test
- public void testDebugEnabled() {
- assertFalse(new MapboxMapOptions().getDebugActive());
- assertTrue(new MapboxMapOptions().debugActive(true).getDebugActive());
- assertFalse(new MapboxMapOptions().debugActive(false).getDebugActive());
- }
-
- @Test
- public void testCompassEnabled() {
- assertTrue(new MapboxMapOptions().compassEnabled(true).getCompassEnabled());
- assertFalse(new MapboxMapOptions().compassEnabled(false).getCompassEnabled());
- }
-
- @Test
- public void testCompassGravity() {
- assertEquals(Gravity.TOP | Gravity.END, new MapboxMapOptions().getCompassGravity());
- assertEquals(Gravity.BOTTOM, new MapboxMapOptions().compassGravity(Gravity.BOTTOM).getCompassGravity());
- assertNotEquals(Gravity.START, new MapboxMapOptions().compassGravity(Gravity.BOTTOM).getCompassGravity());
- }
-
- @Test
- public void testCompassMargins() {
- assertTrue(Arrays.equals(new int[]{0, 1, 2, 3}, new MapboxMapOptions().compassMargins(new int[]{0, 1, 2, 3}).getCompassMargins()));
- assertFalse(Arrays.equals(new int[]{0, 1, 2, 3}, new MapboxMapOptions().compassMargins(new int[]{0, 0, 0, 0}).getCompassMargins()));
- }
-
- @Test
- public void testLogoEnabled() {
- assertTrue(new MapboxMapOptions().logoEnabled(true).getLogoEnabled());
- assertFalse(new MapboxMapOptions().logoEnabled(false).getLogoEnabled());
- }
-
- @Test
- public void testLogoGravity() {
- assertEquals(Gravity.BOTTOM | Gravity.START, new MapboxMapOptions().getLogoGravity());
- assertEquals(Gravity.BOTTOM, new MapboxMapOptions().logoGravity(Gravity.BOTTOM).getLogoGravity());
- assertNotEquals(Gravity.START, new MapboxMapOptions().logoGravity(Gravity.BOTTOM).getLogoGravity());
- }
-
- @Test
- public void testLogoMargins() {
- assertTrue(Arrays.equals(new int[]{0, 1, 2, 3}, new MapboxMapOptions().logoMargins(new int[]{0, 1, 2, 3}).getLogoMargins()));
- assertFalse(Arrays.equals(new int[]{0, 1, 2, 3}, new MapboxMapOptions().logoMargins(new int[]{0, 0, 0, 0}).getLogoMargins()));
- }
-
- @Test
- public void testAttributionTintColor() {
- assertEquals(-1, new MapboxMapOptions().getAttributionTintColor());
- assertEquals(Color.RED, new MapboxMapOptions().attributionTintColor(Color.RED).getAttributionTintColor());
- }
-
- @Test
- public void testAttributionEnabled() {
- assertTrue(new MapboxMapOptions().attributionEnabled(true).getAttributionEnabled());
- assertFalse(new MapboxMapOptions().attributionEnabled(false).getAttributionEnabled());
- }
-
- @Test
- public void testAttributionGravity() {
- assertEquals(Gravity.BOTTOM, new MapboxMapOptions().getAttributionGravity());
- assertEquals(Gravity.BOTTOM, new MapboxMapOptions().attributionGravity(Gravity.BOTTOM).getAttributionGravity());
- assertNotEquals(Gravity.START, new MapboxMapOptions().attributionGravity(Gravity.BOTTOM).getAttributionGravity());
- }
-
- @Test
- public void testAttributionMargins() {
- assertTrue(Arrays.equals(new int[]{0, 1, 2, 3}, new MapboxMapOptions().attributionMargins(new int[]{0, 1, 2, 3}).getAttributionMargins()));
- assertFalse(Arrays.equals(new int[]{0, 1, 2, 3}, new MapboxMapOptions().attributionMargins(new int[]{0, 0, 0, 0}).getAttributionMargins()));
- }
-
- @Test
- public void testMinZoom() {
- assertEquals(MapboxConstants.MINIMUM_ZOOM, new MapboxMapOptions().getMinZoom());
- assertEquals(5.0f, new MapboxMapOptions().minZoom(5.0f).getMinZoom());
- assertNotEquals(2.0f, new MapboxMapOptions().minZoom(5.0f).getMinZoom());
- }
-
- @Test
- public void testMaxZoom() {
- assertEquals(MapboxConstants.MAXIMUM_ZOOM, new MapboxMapOptions().getMaxZoom());
- assertEquals(5.0f, new MapboxMapOptions().maxZoom(5.0f).getMaxZoom());
- assertNotEquals(2.0f, new MapboxMapOptions().maxZoom(5.0f).getMaxZoom());
- }
-
- @Test
- public void testLocationEnabled() {
- assertFalse(new MapboxMapOptions().getLocationEnabled());
- assertTrue(new MapboxMapOptions().locationEnabled(true).getLocationEnabled());
- assertFalse(new MapboxMapOptions().locationEnabled(false).getLocationEnabled());
- }
-
- @Test
- public void testTiltGesturesEnabled() {
- assertTrue(new MapboxMapOptions().getTiltGesturesEnabled());
- assertTrue(new MapboxMapOptions().tiltGesturesEnabled(true).getTiltGesturesEnabled());
- assertFalse(new MapboxMapOptions().tiltGesturesEnabled(false).getTiltGesturesEnabled());
- }
-
- @Test
- public void testScrollGesturesEnabled() {
- assertTrue(new MapboxMapOptions().getScrollGesturesEnabled());
- assertTrue(new MapboxMapOptions().scrollGesturesEnabled(true).getScrollGesturesEnabled());
- assertFalse(new MapboxMapOptions().scrollGesturesEnabled(false).getScrollGesturesEnabled());
- }
-
- @Test
- public void testZoomGesturesEnabled() {
- assertTrue(new MapboxMapOptions().getZoomGesturesEnabled());
- assertTrue(new MapboxMapOptions().zoomGesturesEnabled(true).getZoomGesturesEnabled());
- assertFalse(new MapboxMapOptions().zoomGesturesEnabled(false).getZoomGesturesEnabled());
- }
-
- @Test
- public void testRotateGesturesEnabled() {
- assertTrue(new MapboxMapOptions().getRotateGesturesEnabled());
- assertTrue(new MapboxMapOptions().rotateGesturesEnabled(true).getRotateGesturesEnabled());
- assertFalse(new MapboxMapOptions().rotateGesturesEnabled(false).getRotateGesturesEnabled());
- }
-
- @Test
- public void testZoomControlsEnabled() {
- assertFalse(new MapboxMapOptions().getZoomControlsEnabled());
- assertTrue(new MapboxMapOptions().zoomControlsEnabled(true).getZoomControlsEnabled());
- assertFalse(new MapboxMapOptions().zoomControlsEnabled(false).getZoomControlsEnabled());
- }
-
- @Test
- public void testStyleUrl() {
- assertEquals(Style.DARK, new MapboxMapOptions().styleUrl(Style.DARK).getStyle());
- assertNotEquals(Style.LIGHT, new MapboxMapOptions().styleUrl(Style.DARK).getStyle());
- assertNull(new MapboxMapOptions().getStyle());
- }
-
- @Test
- public void testCamera() {
- CameraPosition position = new CameraPosition.Builder().build();
- assertEquals(new CameraPosition.Builder(position).build(), new MapboxMapOptions().camera(position).getCamera());
- assertNotEquals(new CameraPosition.Builder().target(new LatLng(1, 1)), new MapboxMapOptions().camera(position));
- assertNull(new MapboxMapOptions().getCamera());
- }
-
- @Test
- public void testMyLocationForegroundTint() {
- assertEquals(Color.BLUE, new MapboxMapOptions().myLocationForegroundTintColor(Color.BLUE).getMyLocationForegroundTintColor());
- }
-
- @Test
- public void testMyLocationBackgroundTint() {
- assertEquals(Color.BLUE, new MapboxMapOptions().myLocationBackgroundTintColor(Color.BLUE).getMyLocationBackgroundTintColor());
- }
-
- @Test
- public void testParceable() {
- MapboxMapOptions options = new MapboxMapOptions().camera(new CameraPosition.Builder().build()).styleUrl("s").accessToken("a").debugActive(true).compassMargins(new int[]{0, 1, 2, 3});
- MapboxMapOptions parceled = (MapboxMapOptions) MockParcel.obtain(options);
- assertEquals(options, parceled);
- }
-
- @Test
- public void testAccessToken() {
- assertNull(new MapboxMapOptions().getAccessToken());
- assertEquals("test", new MapboxMapOptions().accessToken("test").getAccessToken());
- assertNotEquals("nottest", new MapboxMapOptions().accessToken("test").getStyle());
- }
+ private static final double DELTA = 1e-15;
+
+ @Test
+ public void testSanity() {
+ assertNotNull("should not be null", new MapboxMapOptions());
+ }
+
+ @Test
+ public void testDebugEnabled() {
+ assertFalse(new MapboxMapOptions().getDebugActive());
+ assertTrue(new MapboxMapOptions().debugActive(true).getDebugActive());
+ assertFalse(new MapboxMapOptions().debugActive(false).getDebugActive());
+ }
+
+ @Test
+ public void testCompassEnabled() {
+ assertTrue(new MapboxMapOptions().compassEnabled(true).getCompassEnabled());
+ assertFalse(new MapboxMapOptions().compassEnabled(false).getCompassEnabled());
+ }
+
+ @Test
+ public void testCompassGravity() {
+ assertEquals(Gravity.TOP | Gravity.END, new MapboxMapOptions().getCompassGravity());
+ assertEquals(Gravity.BOTTOM, new MapboxMapOptions().compassGravity(Gravity.BOTTOM).getCompassGravity());
+ assertNotEquals(Gravity.START, new MapboxMapOptions().compassGravity(Gravity.BOTTOM).getCompassGravity());
+ }
+
+ @Test
+ public void testCompassMargins() {
+ assertTrue(Arrays.equals(new int[] {0, 1, 2, 3}, new MapboxMapOptions().compassMargins(
+ new int[] {0, 1, 2, 3}).getCompassMargins()));
+ assertFalse(Arrays.equals(new int[] {0, 1, 2, 3}, new MapboxMapOptions().compassMargins(
+ new int[] {0, 0, 0, 0}).getCompassMargins()));
+ }
+
+ @Test
+ public void testLogoEnabled() {
+ assertTrue(new MapboxMapOptions().logoEnabled(true).getLogoEnabled());
+ assertFalse(new MapboxMapOptions().logoEnabled(false).getLogoEnabled());
+ }
+
+ @Test
+ public void testLogoGravity() {
+ assertEquals(Gravity.BOTTOM | Gravity.START, new MapboxMapOptions().getLogoGravity());
+ assertEquals(Gravity.BOTTOM, new MapboxMapOptions().logoGravity(Gravity.BOTTOM).getLogoGravity());
+ assertNotEquals(Gravity.START, new MapboxMapOptions().logoGravity(Gravity.BOTTOM).getLogoGravity());
+ }
+
+ @Test
+ public void testLogoMargins() {
+ assertTrue(Arrays.equals(new int[] {0, 1, 2, 3}, new MapboxMapOptions().logoMargins(
+ new int[] {0, 1, 2, 3}).getLogoMargins()));
+ assertFalse(Arrays.equals(new int[] {0, 1, 2, 3}, new MapboxMapOptions().logoMargins(
+ new int[] {0, 0, 0, 0}).getLogoMargins()));
+ }
+
+ @Test
+ public void testAttributionTintColor() {
+ assertEquals(-1, new MapboxMapOptions().getAttributionTintColor());
+ assertEquals(Color.RED, new MapboxMapOptions().attributionTintColor(Color.RED).getAttributionTintColor());
+ }
+
+ @Test
+ public void testAttributionEnabled() {
+ assertTrue(new MapboxMapOptions().attributionEnabled(true).getAttributionEnabled());
+ assertFalse(new MapboxMapOptions().attributionEnabled(false).getAttributionEnabled());
+ }
+
+ @Test
+ public void testAttributionGravity() {
+ assertEquals(Gravity.BOTTOM, new MapboxMapOptions().getAttributionGravity());
+ assertEquals(Gravity.BOTTOM, new MapboxMapOptions().attributionGravity(Gravity.BOTTOM).getAttributionGravity());
+ assertNotEquals(Gravity.START, new MapboxMapOptions().attributionGravity(Gravity.BOTTOM).getAttributionGravity());
+ }
+
+ @Test
+ public void testAttributionMargins() {
+ assertTrue(Arrays.equals(new int[] {0, 1, 2, 3}, new MapboxMapOptions().attributionMargins(
+ new int[] {0, 1, 2, 3}).getAttributionMargins()));
+ assertFalse(Arrays.equals(new int[] {0, 1, 2, 3}, new MapboxMapOptions().attributionMargins(
+ new int[] {0, 0, 0, 0}).getAttributionMargins()));
+ }
+
+ @Test
+ public void testMinZoom() {
+ assertEquals(MapboxConstants.MINIMUM_ZOOM, new MapboxMapOptions().getMinZoomPreference(), DELTA);
+ assertEquals(5.0f, new MapboxMapOptions().minZoomPreference(5.0f).getMinZoomPreference(), DELTA);
+ assertNotEquals(2.0f, new MapboxMapOptions().minZoomPreference(5.0f).getMinZoomPreference(), DELTA);
+ }
+
+ @Test
+ public void testMaxZoom() {
+ assertEquals(MapboxConstants.MAXIMUM_ZOOM, new MapboxMapOptions().getMaxZoomPreference(), DELTA);
+ assertEquals(5.0f, new MapboxMapOptions().maxZoomPreference(5.0f).getMaxZoomPreference(), DELTA);
+ assertNotEquals(2.0f, new MapboxMapOptions().maxZoomPreference(5.0f).getMaxZoomPreference(), DELTA);
+ }
+
+ @Test
+ public void testLocationEnabled() {
+ assertFalse(new MapboxMapOptions().getLocationEnabled());
+ assertTrue(new MapboxMapOptions().locationEnabled(true).getLocationEnabled());
+ assertFalse(new MapboxMapOptions().locationEnabled(false).getLocationEnabled());
+ }
+
+ @Test
+ public void testTiltGesturesEnabled() {
+ assertTrue(new MapboxMapOptions().getTiltGesturesEnabled());
+ assertTrue(new MapboxMapOptions().tiltGesturesEnabled(true).getTiltGesturesEnabled());
+ assertFalse(new MapboxMapOptions().tiltGesturesEnabled(false).getTiltGesturesEnabled());
+ }
+
+ @Test
+ public void testScrollGesturesEnabled() {
+ assertTrue(new MapboxMapOptions().getScrollGesturesEnabled());
+ assertTrue(new MapboxMapOptions().scrollGesturesEnabled(true).getScrollGesturesEnabled());
+ assertFalse(new MapboxMapOptions().scrollGesturesEnabled(false).getScrollGesturesEnabled());
+ }
+
+ @Test
+ public void testZoomGesturesEnabled() {
+ assertTrue(new MapboxMapOptions().getZoomGesturesEnabled());
+ assertTrue(new MapboxMapOptions().zoomGesturesEnabled(true).getZoomGesturesEnabled());
+ assertFalse(new MapboxMapOptions().zoomGesturesEnabled(false).getZoomGesturesEnabled());
+ }
+
+ @Test
+ public void testRotateGesturesEnabled() {
+ assertTrue(new MapboxMapOptions().getRotateGesturesEnabled());
+ assertTrue(new MapboxMapOptions().rotateGesturesEnabled(true).getRotateGesturesEnabled());
+ assertFalse(new MapboxMapOptions().rotateGesturesEnabled(false).getRotateGesturesEnabled());
+ }
+
+ @Test
+ public void testZoomControlsEnabled() {
+ assertFalse(new MapboxMapOptions().getZoomControlsEnabled());
+ assertTrue(new MapboxMapOptions().zoomControlsEnabled(true).getZoomControlsEnabled());
+ assertFalse(new MapboxMapOptions().zoomControlsEnabled(false).getZoomControlsEnabled());
+ }
+
+ @Test
+ public void testStyleUrl() {
+ assertEquals(Style.DARK, new MapboxMapOptions().styleUrl(Style.DARK).getStyle());
+ assertNotEquals(Style.LIGHT, new MapboxMapOptions().styleUrl(Style.DARK).getStyle());
+ assertNull(new MapboxMapOptions().getStyle());
+ }
+
+ @Test
+ public void testCamera() {
+ CameraPosition position = new CameraPosition.Builder().build();
+ assertEquals(new CameraPosition.Builder(position).build(), new MapboxMapOptions().camera(position).getCamera());
+ assertNotEquals(new CameraPosition.Builder().target(new LatLng(1, 1)), new MapboxMapOptions().camera(position));
+ assertNull(new MapboxMapOptions().getCamera());
+ }
+
+ @Test
+ public void testMyLocationForegroundTint() {
+ assertEquals(Color.BLUE, new MapboxMapOptions()
+ .myLocationForegroundTintColor(Color.BLUE).getMyLocationForegroundTintColor());
+ }
+
+ @Test
+ public void testMyLocationBackgroundTint() {
+ assertEquals(Color.BLUE, new MapboxMapOptions()
+ .myLocationBackgroundTintColor(Color.BLUE).getMyLocationBackgroundTintColor());
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
deleted file mode 100644
index 9d0a1c0ad7..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
+++ /dev/null
@@ -1,868 +0,0 @@
-package com.mapbox.mapboxsdk.maps;
-
-import android.graphics.Color;
-import android.graphics.Point;
-import android.graphics.PointF;
-
-import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
-import com.mapbox.mapboxsdk.annotations.Marker;
-import com.mapbox.mapboxsdk.annotations.MarkerOptions;
-import com.mapbox.mapboxsdk.annotations.Polygon;
-import com.mapbox.mapboxsdk.annotations.PolygonOptions;
-import com.mapbox.mapboxsdk.annotations.Polyline;
-import com.mapbox.mapboxsdk.annotations.PolylineOptions;
-import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.exceptions.InvalidMarkerPositionException;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.geometry.LatLngBounds;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class MapboxMapTest {
-
- private MapboxMap mMapboxMap;
-
- @InjectMocks
- MapView mMapView = mock(MapView.class);
-
- @Mock
- MapboxMap.OnMarkerClickListener mOnMarkerClickListener;
-
- @Mock
- MapboxMap.OnCameraChangeListener mOnCameraChangeListener;
-
- @Mock
- MapboxMap.InfoWindowAdapter mInfoWindowAdapter;
-
- @Mock
- MapboxMap.OnScrollListener mScrollListener;
-
- @Mock
- MapboxMap.OnFlingListener mFlingListener;
-
- @Mock
- MapboxMap.OnFpsChangedListener mFpsChangedListener;
-
- @Mock
- MapboxMap.OnInfoWindowClickListener mWindowClickListener;
-
- @Mock
- MapboxMap.OnInfoWindowCloseListener mWindowCloseListener;
-
- @Mock
- MapboxMap.OnInfoWindowLongClickListener mWindowLongClickListener;
-
- @Mock
- MapboxMap.OnMyLocationChangeListener mLocationChangeListener;
-
- @Mock
- MapboxMap.OnMyLocationTrackingModeChangeListener mMyLocationTrackingModeChangeListener;
-
- @Mock
- MapboxMap.OnMyBearingTrackingModeChangeListener mMyBearingTrackingModeChangeListener;
-
- @Before
- public void beforeTest() {
- MockitoAnnotations.initMocks(this);
- mMapboxMap = new MapboxMap(mMapView);
- }
-
- @Test
- public void testSanity() {
- assertNotNull("mMapboxMap should not be null", mMapboxMap);
- }
-
- @Test
- public void testMock() {
- assertNotNull("mMapView should be mocked", mMapView);
- }
-
- @Test
- public void testGetMapView() {
- assertNotNull("MapView should be non null", mMapboxMap.getMapView());
- }
-
- //
- // UiSettings
- //
-
- @Test
- public void testUiSettings() {
- assertNotNull("UiSettings should not be null", mMapboxMap.getUiSettings());
- }
-
- //
- // MinZoomLevel
- //
-
- @Test
- public void testMinZoom() {
- double zoom = 10;
- mMapboxMap.setMinZoom(zoom);
- assertEquals("MinZoom should match", zoom, mMapboxMap.getMinZoom(), 0);
- }
-
- @Test
- public void testMaxZoom() {
- double zoom = 10;
- mMapboxMap.setMaxZoom(zoom);
- assertEquals("MaxZoom should match", zoom, mMapboxMap.getMaxZoom(), 0);
- }
-
- @Test
- public void testInitialZoomLevels() {
- assertEquals("MaxZoom should match", 0, mMapboxMap.getMaxZoom(), 0);
- assertEquals("MinZoom should match", 0, mMapboxMap.getMinZoom(), 0);
- }
-
- //
- // TrackingSettings
- //
-
- @Test
- public void testTrackingSettings() {
- assertNotNull("TrackingSettings should not be null", mMapboxMap.getTrackingSettings());
- }
-
- //
- // Projection
- //
-
- @Test
- public void testProjection() {
- assertNotNull("Projection should not be null", mMapboxMap.getProjection());
- }
-
- //
- // InfoWindow
- //
-
- @Test
- public void testConcurrentInfoWindowEnabled() {
- mMapboxMap.setAllowConcurrentMultipleOpenInfoWindows(true);
- assertTrue("ConcurrentWindows should be true", mMapboxMap.isAllowConcurrentMultipleOpenInfoWindows());
- }
-
- @Test
- public void testConcurrentInfoWindowDisabled() {
- mMapboxMap.setAllowConcurrentMultipleOpenInfoWindows(false);
- assertFalse("ConcurrentWindows should be false", mMapboxMap.isAllowConcurrentMultipleOpenInfoWindows());
- }
-
- @Test
- public void testInfoWindowAdapter() {
- mMapboxMap.setInfoWindowAdapter(mInfoWindowAdapter);
- assertEquals("InfoWindowAdpter should be the same", mInfoWindowAdapter, mMapboxMap.getInfoWindowAdapter());
- }
-
- //
- // Location
- //
-
- @Test
- public void testMyLocationEnabled() {
- when(mMapView.isPermissionsAccepted()).thenReturn(true);
- mMapboxMap.setMyLocationEnabled(true);
- assertTrue("MyLocationEnabled should be true", mMapboxMap.isMyLocationEnabled());
-
- }
-
- @Test
- public void testMyLocationDisabled() {
- when(mMapView.isPermissionsAccepted()).thenReturn(true);
- mMapboxMap.setMyLocationEnabled(false);
- assertFalse("MyLocationEnabled should be false", mMapboxMap.isMyLocationEnabled());
- }
-
- //
- // padding
- //
-
- @Test
- public void testPadding() {
- mMapboxMap.setOnCameraChangeListener(mOnCameraChangeListener);
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(position));
- mMapboxMap.setPadding(0, 0, 0, 0);
- verify(mOnCameraChangeListener, times(1)).onCameraChange(position);
- }
-
- //
- // setters/getters interfaces
- //
-
- @Test
- public void testScrollListener() {
- mMapboxMap.setOnScrollListener(mScrollListener);
- assertEquals("ScrollListener should match", mScrollListener, mMapboxMap.getOnScrollListener());
- }
-
- @Test
- public void testFlingListener() {
- mMapboxMap.setOnFlingListener(mFlingListener);
- assertEquals("FlingListener should match", mFlingListener, mMapboxMap.getOnFlingListener());
- }
-
- @Test
- public void testFpsListener() {
- mMapboxMap.setOnFpsChangedListener(mFpsChangedListener);
- assertEquals("FpsListener should match", mFpsChangedListener, mMapboxMap.getOnFpsChangedListener());
- }
-
- @Test
- public void testInfoWindowClickListener() {
- mMapboxMap.setOnInfoWindowClickListener(mWindowClickListener);
- assertEquals("InfoWidowClickListener should match", mWindowClickListener, mMapboxMap.getOnInfoWindowClickListener());
- }
-
- @Test
- public void testInfoWindowCloseListener() {
- mMapboxMap.setOnInfoWindowCloseListener(mWindowCloseListener);
- assertEquals("InfoWindowCloseListener should match", mWindowCloseListener, mMapboxMap.getOnInfoWindowCloseListener());
- }
-
- @Test
- public void testInfoWindowLongClickListener() {
- mMapboxMap.setOnInfoWindowLongClickListener(mWindowLongClickListener);
- assertEquals("InfoWindowLongClickListener should match", mWindowLongClickListener, mMapboxMap.getOnInfoWindowLongClickListener());
- }
-
- @Test
- public void testOnBearingTrackingModeChangeListener() {
- mMapboxMap.setOnMyBearingTrackingModeChangeListener(mMyBearingTrackingModeChangeListener);
- assertEquals("MyBearingTrackingChangeListerner should match", mMyBearingTrackingModeChangeListener, mMapboxMap.getOnMyBearingTrackingModeChangeListener());
- }
-
- @Test
- public void testOnLocationTrackingModeChangeListener() {
- mMapboxMap.setOnMyLocationTrackingModeChangeListener(mMyLocationTrackingModeChangeListener);
- assertEquals("MyLocationTrackigChangeListener should match", mMyLocationTrackingModeChangeListener, mMapboxMap.getOnMyLocationTrackingModeChangeListener());
- }
-
- //
- // CameraPosition
- //
-
- @Test
- public void testCameraPosition() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- assertEquals("CameraPosition should be same", position, mMapboxMap.getCameraPosition());
- }
-
- //
- // Camera - moveCamera
- //
-
- @Test
- public void testNewCameraPositionMoveCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(position));
- assertEquals("CameraPosition should be same", position, mMapboxMap.getCameraPosition());
- }
-
- //
- // Camera - animateCamera
- //
-
- @Test
- public void testNewCameraPositionAnimateCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(position));
- assertEquals("CameraPosition should be same", position, mMapboxMap.getCameraPosition());
- }
-
- @Test
- public void testNewCameraPositionAnimateCameraWithCallbackParameter() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(position), null);
- assertEquals("CameraPosition should be same", position, mMapboxMap.getCameraPosition());
- }
-
- @Test
- public void testNewCameraPositionAnimateCameraWithDurationParameter() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(position), 0);
- assertEquals("CameraPosition should be same", position, mMapboxMap.getCameraPosition());
- }
-
- @Test
- public void testNewCameraPositionAnimateCameraWithDurationAndCallbackParameter() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(position), 0, null);
- assertEquals("CameraPosition should be same", position, mMapboxMap.getCameraPosition());
- }
-
- //
- // Camera - easeCamera
- //
-
- @Test
- public void testNewCameraPositionEaseCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(position));
- assertEquals("CameraPosition should be same", position, mMapboxMap.getCameraPosition());
- }
-
- @Test
- public void testNewCameraPositionEaseCameraWithCallbackParameter() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(position), 1000, null);
- assertEquals("CameraPosition should be same", position, mMapboxMap.getCameraPosition());
- }
-
- //
- // Camera - LatLng
- //
-
- @Test
- public void testLatLngMoveCamera() {
- mMapboxMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(4, 5)));
- assertEquals("LatLng should be same", new LatLng(4, 5), mMapboxMap.getCameraPosition().target);
- }
-
- @Test
- public void testLatLngAnimateCamera() {
- mMapboxMap.animateCamera(CameraUpdateFactory.newLatLng(new LatLng(4, 5)));
- assertEquals("LatLng should be same", new LatLng(4, 5), mMapboxMap.getCameraPosition().target);
- }
-
- @Test
- public void testLatLngEaseCamera() {
- mMapboxMap.easeCamera(CameraUpdateFactory.newLatLng(new LatLng(4, 5)), 1000);
- assertEquals("LatLng should be same", new LatLng(4, 5), mMapboxMap.getCameraPosition().target);
- }
-
- //
- // Camera - LatLngZoom
- //
-
- @Test
- public void testLatLngZoomMoveCamera() {
- mMapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(4, 5), 10));
- assertEquals("LatLng should be same", new LatLng(4, 5), mMapboxMap.getCameraPosition().target);
- assertTrue("Zoomlevel should be same", 10 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testLatLngZoomAnimateCamera() {
- mMapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(4, 5), 10));
- assertEquals("LatLng should be same", new LatLng(4, 5), mMapboxMap.getCameraPosition().target);
- assertTrue("Zoomlevel should be same", 10 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testLatLngZoomEaseCamera() {
- mMapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(4, 5), 10), 1000);
- assertEquals("LatLng should be same", new LatLng(4, 5), mMapboxMap.getCameraPosition().target);
- assertTrue("Zoomlevel should be same", 10 == mMapboxMap.getCameraPosition().zoom);
- }
-
- //
- // Camera - LatLngBounds
- //
- @Test
- public void testLatLngBounds() {
- LatLng la = new LatLng(34.053940, -118.242622);
- LatLng ny = new LatLng(40.712730, -74.005953);
- LatLng centroid = new LatLng(
- (la.getLatitude() + ny.getLatitude()) / 2,
- (la.getLongitude() + ny.getLongitude()) / 2);
-
- Projection projection = mock(Projection.class);
- when(projection.toScreenLocation(la)).thenReturn(new PointF(20, 20));
- when(projection.toScreenLocation(ny)).thenReturn(new PointF(100, 100));
- when(projection.fromScreenLocation(any(PointF.class))).thenReturn(centroid);
-
- UiSettings uiSettings = mock(UiSettings.class);
- when(uiSettings.getHeight()).thenReturn(1000f);
-
- mMapboxMap.setProjection(projection);
- mMapboxMap.setUiSettings(uiSettings);
-
- LatLngBounds bounds = new LatLngBounds.Builder().include(la).include(ny).build();
- mMapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 1));
-
- assertEquals("LatLng should be same", centroid, mMapboxMap.getCameraPosition().target);
- }
-
-
- //
- // CameraPositionUpdate - NPX target
- //
- @Test
- public void testCamerePositionUpdateNullTarget() {
- LatLng latLng = new LatLng(1, 1);
- mMapboxMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
- mMapboxMap.moveCamera(CameraUpdateFactory.newLatLng(null));
- assertEquals("LatLng should be same", latLng, mMapboxMap.getCameraPosition().target);
- }
-
- //
- // Camera - ScrollBy
- //
- @Test
- public void testScrollBy() {
- LatLng latLng = new LatLng(1, 1);
- mMapboxMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
- mMapboxMap.moveCamera(CameraUpdateFactory.scrollBy(0, 0));
- assertEquals("LatLng should be same", latLng, mMapboxMap.getCameraPosition().target);
- mMapboxMap.moveCamera(CameraUpdateFactory.scrollBy(12, 12));
- }
-
- //
- // Camera - Zoom
- //
-
- @Test
- public void testZoomInMoveCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.moveCamera(CameraUpdateFactory.zoomIn());
- assertTrue("Zoomlevel should be same", 4 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testZoomOutMoveCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.moveCamera(CameraUpdateFactory.zoomOut());
- assertTrue("Zoomlevel should be same", 2 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testZoomByMoveCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.moveCamera(CameraUpdateFactory.zoomBy(3));
- assertTrue("Zoomlevel should be same", 6 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testZoomByPointMoveCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.moveCamera(CameraUpdateFactory.zoomBy(3, new Point(0, 0)));
- assertTrue("Zoomlevel should be same", 6 == mMapboxMap.getCameraPosition().zoom);
- // todo calculate and check LatLng
- }
-
- @Test
- public void testZoomToMoveCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.moveCamera(CameraUpdateFactory.zoomTo(12));
- assertTrue("Zoomlevel should be same", 12 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testZoomInAnimateCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.animateCamera(CameraUpdateFactory.zoomIn());
- assertTrue("Zoomlevel should be same", 4 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testZoomOutAnimateCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.animateCamera(CameraUpdateFactory.zoomOut());
- assertTrue("Zoomlevel should be same", 2 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testZoomByAnimateCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.animateCamera(CameraUpdateFactory.zoomBy(3));
- assertTrue("Zoomlevel should be same", 6 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testZoomToAnimateCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.animateCamera(CameraUpdateFactory.zoomTo(12));
- assertTrue("Zoomlevel should be same", 12 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testZoomByPointAnimateCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.animateCamera(CameraUpdateFactory.zoomBy(1, new Point(0, 0)));
- assertTrue("Zoomlevel should be same", 4 == mMapboxMap.getCameraPosition().zoom);
- // todo calculate and check LatLng
- }
-
- @Test
- public void testZoomInEaseCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.easeCamera(CameraUpdateFactory.zoomIn(), 1000);
- assertTrue("Zoomlevel should be same", 4 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testZoomOutEaseCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.easeCamera(CameraUpdateFactory.zoomOut(), 1000);
- assertTrue("Zoomlevel should be same", 2 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testZoomByEaseCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.easeCamera(CameraUpdateFactory.zoomBy(3), 1000);
- assertTrue("Zoomlevel should be same", 6 == mMapboxMap.getCameraPosition().zoom);
- }
-
- @Test
- public void testZoomByPointCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.easeCamera(CameraUpdateFactory.zoomBy(3, new Point(0, 0)), 1000);
- assertTrue("Zoomlevel should be same", 6 == mMapboxMap.getCameraPosition().zoom);
- // todo calculate and check LatLng
- }
-
- @Test
- public void testZoomToEaseCamera() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setCameraPosition(position);
- mMapboxMap.easeCamera(CameraUpdateFactory.zoomTo(12), 1000);
- assertTrue("Zoomlevel should be same", 12 == mMapboxMap.getCameraPosition().zoom);
- }
-
- //
- // OnCameraChangeListener
- //
-
- @Test
- public void testOnCameraChangeListener() {
- CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
- mMapboxMap.setOnCameraChangeListener(mOnCameraChangeListener);
- mMapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(position));
- verify(mOnCameraChangeListener, times(1)).onCameraChange(position);
- }
-
- //
- // Annotations
- //
-
- @Test
- public void testAddMarker() {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker marker = mMapboxMap.addMarker(markerOptions);
- assertTrue("Marker should be contained", mMapboxMap.getMarkers().contains(marker));
- }
-
- @Test(expected = InvalidMarkerPositionException.class)
- public void testAddMarkerInvalidPosition(){
- new MarkerOptions().getMarker();
- }
-
- @Test
- public void testAddMarkers() {
- List<BaseMarkerOptions> markerList = new ArrayList<>();
- MarkerOptions markerOptions1 = new MarkerOptions().position(new LatLng()).title("a");
- MarkerOptions markerOptions2 = new MarkerOptions().position(new LatLng()).title("b");
- markerList.add(markerOptions1);
- markerList.add(markerOptions2);
- List<Marker> markers = mMapboxMap.addMarkers(markerList);
- assertEquals("Markers size should be 2", 2, mMapboxMap.getMarkers().size());
- assertTrue(mMapboxMap.getMarkers().contains(markers.get(0)));
- assertTrue(mMapboxMap.getMarkers().contains(markers.get(1)));
- }
-
- @Test
- public void testAddMarkersEmpty() {
- List<BaseMarkerOptions> markerList = new ArrayList<>();
- mMapboxMap.addMarkers(markerList);
- assertEquals("Markers size should be 0", 0, mMapboxMap.getMarkers().size());
- }
-
- @Test
- public void testAddMarkersSingleMarker() {
- List<BaseMarkerOptions> markerList = new ArrayList<>();
- MarkerOptions markerOptions = new MarkerOptions().title("a").position(new LatLng());
- markerList.add(markerOptions);
- List<Marker> markers = mMapboxMap.addMarkers(markerList);
- assertEquals("Markers size should be 1", 1, mMapboxMap.getMarkers().size());
- assertTrue(mMapboxMap.getMarkers().contains(markers.get(0)));
- }
-
- @Test
- public void testAddPolygon() {
- PolygonOptions polygonOptions = new PolygonOptions().add(new LatLng());
- Polygon polygon = mMapboxMap.addPolygon(polygonOptions);
- assertTrue("Polygon should be contained", mMapboxMap.getPolygons().contains(polygon));
- }
-
- @Test
- public void testAddEmptyPolygon() {
- PolygonOptions polygonOptions = new PolygonOptions();
- Polygon polygon = mMapboxMap.addPolygon(polygonOptions);
- assertTrue("Polygon should be ignored", !mMapboxMap.getPolygons().contains(polygon));
- }
-
- @Test
- public void testAddPolygons() {
- List<PolygonOptions> polygonList = new ArrayList<>();
- PolygonOptions polygonOptions1 = new PolygonOptions().fillColor(Color.BLACK).add(new LatLng());
- PolygonOptions polygonOptions2 = new PolygonOptions().fillColor(Color.WHITE).add(new LatLng());
- PolygonOptions polygonOptions3 = new PolygonOptions();
- polygonList.add(polygonOptions1);
- polygonList.add(polygonOptions2);
- polygonList.add(polygonOptions3);
- mMapboxMap.addPolygons(polygonList);
- assertEquals("Polygons size should be 2", 2, mMapboxMap.getPolygons().size());
- assertTrue(mMapboxMap.getPolygons().contains(polygonOptions1.getPolygon()));
- assertTrue(mMapboxMap.getPolygons().contains(polygonOptions2.getPolygon()));
- assertTrue("Polygon should be ignored", !mMapboxMap.getPolygons().contains(polygonOptions3.getPolygon()));
- }
-
- @Test
- public void addPolygonsEmpty() {
- mMapboxMap.addPolygons(new ArrayList<PolygonOptions>());
- assertEquals("Polygons size should be 0", 0, mMapboxMap.getPolygons().size());
- }
-
- @Test
- public void addPolygonsSingle() {
- List<PolygonOptions> polygonList = new ArrayList<>();
- PolygonOptions polygonOptions = new PolygonOptions().fillColor(Color.BLACK).add(new LatLng());
- polygonList.add(polygonOptions);
- mMapboxMap.addPolygons(polygonList);
- assertEquals("Polygons size should be 1", 1, mMapboxMap.getPolygons().size());
- assertTrue(mMapboxMap.getPolygons().contains(polygonOptions.getPolygon()));
- }
-
- @Test
- public void testAddPolyline() {
- PolylineOptions polylineOptions = new PolylineOptions().add(new LatLng());
- Polyline polyline = mMapboxMap.addPolyline(polylineOptions);
- assertTrue("Polyline should be contained", mMapboxMap.getPolylines().contains(polyline));
- }
-
- @Test
- public void testAddEmptyPolyline() {
- PolylineOptions polylineOptions = new PolylineOptions();
- Polyline polyline = mMapboxMap.addPolyline(polylineOptions);
- assertTrue("Polyline should be ignored", !mMapboxMap.getPolylines().contains(polyline));
- }
-
- @Test
- public void testAddPolylines() {
- List<PolylineOptions> polylineList = new ArrayList<>();
- PolylineOptions polygonOptions1 = new PolylineOptions().color(Color.BLACK).add(new LatLng());
- PolylineOptions polygonOptions2 = new PolylineOptions().color(Color.WHITE).add(new LatLng());
- PolylineOptions polygonOptions3 = new PolylineOptions();
- polylineList.add(polygonOptions1);
- polylineList.add(polygonOptions2);
- polylineList.add(polygonOptions3);
- mMapboxMap.addPolylines(polylineList);
- assertEquals("Polygons size should be 2", 2, mMapboxMap.getPolylines().size());
- assertTrue(mMapboxMap.getPolylines().contains(polygonOptions1.getPolyline()));
- assertTrue(mMapboxMap.getPolylines().contains(polygonOptions2.getPolyline()));
- assertTrue("Polyline should be ignored", !mMapboxMap.getPolylines().contains(polygonOptions3.getPolyline()));
- }
-
- @Test
- public void testAddPolylinesEmpty() {
- mMapboxMap.addPolylines(new ArrayList<PolylineOptions>());
- assertEquals("Polygons size should be 0", 0, mMapboxMap.getPolylines().size());
- }
-
- @Test
- public void testAddPolylinesSingle() {
- List<PolylineOptions> polylineList = new ArrayList<>();
- PolylineOptions polygonOptions = new PolylineOptions().color(Color.BLACK).add(new LatLng());
- polylineList.add(polygonOptions);
- mMapboxMap.addPolylines(polylineList);
- assertEquals("Polygons size should be 1", 1, mMapboxMap.getPolylines().size());
- assertTrue(mMapboxMap.getPolylines().contains(polygonOptions.getPolyline()));
- }
-
- @Test
- public void testRemoveMarker() {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker marker = mMapboxMap.addMarker(markerOptions);
- mMapboxMap.removeMarker(marker);
- assertTrue("Markers should be empty", mMapboxMap.getMarkers().isEmpty());
- }
-
- @Test
- public void testRemovePolygon() {
- PolygonOptions polygonOptions = new PolygonOptions();
- Polygon polygon = mMapboxMap.addPolygon(polygonOptions);
- mMapboxMap.removePolygon(polygon);
- assertTrue("Polygons should be empty", mMapboxMap.getPolylines().isEmpty());
- }
-
- @Test
- public void testRemovePolyline() {
- PolylineOptions polylineOptions = new PolylineOptions();
- Polyline polyline = mMapboxMap.addPolyline(polylineOptions);
- mMapboxMap.removePolyline(polyline);
- assertTrue("Polylines should be empty", mMapboxMap.getPolylines().isEmpty());
- }
-
- @Test
- public void testRemoveAnnotation() {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker marker = mMapboxMap.addMarker(markerOptions);
- mMapboxMap.removeAnnotation(marker);
- assertTrue("Annotations should be empty", mMapboxMap.getAnnotations().isEmpty());
- }
-
- @Test
- public void testRemoveAnnotationById() {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- mMapboxMap.addMarker(markerOptions);
- // id will always be 0 in unit tests
- mMapboxMap.removeAnnotation(0);
- assertTrue("Annotations should be empty", mMapboxMap.getAnnotations().isEmpty());
- }
-
- @Test
- public void testRemoveAnnotations() {
- List<BaseMarkerOptions> markerList = new ArrayList<>();
- MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
- MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
- markerList.add(markerOptions1);
- markerList.add(markerOptions2);
- mMapboxMap.addMarkers(markerList);
- mMapboxMap.removeAnnotations();
- assertTrue("Annotations should be empty", mMapboxMap.getAnnotations().isEmpty());
- }
-
- @Test
- public void testClear() {
- List<BaseMarkerOptions> markerList = new ArrayList<>();
- MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
- MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
- markerList.add(markerOptions1);
- markerList.add(markerOptions2);
- mMapboxMap.addMarkers(markerList);
- mMapboxMap.clear();
- assertTrue("Annotations should be empty", mMapboxMap.getAnnotations().isEmpty());
- }
-
- @Test
- public void testRemoveAnnotationsByList() {
- List<BaseMarkerOptions> markerList = new ArrayList<>();
- MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
- MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
- markerList.add(markerOptions1);
- markerList.add(markerOptions2);
- List<Marker> markers = mMapboxMap.addMarkers(markerList);
- Marker marker = mMapboxMap.addMarker(new MarkerOptions().position(new LatLng()).title("c"));
- mMapboxMap.removeAnnotations(markers);
- assertTrue("Annotations should not be empty", mMapboxMap.getAnnotations().size() == 1);
- assertTrue("Marker should be contained", mMapboxMap.getAnnotations().contains(marker));
- }
-
- @Test
- public void testGetAnnotationById() {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker initialMarker = mMapboxMap.addMarker(markerOptions);
- Marker retrievedMarker = (Marker) mMapboxMap.getAnnotation(0);
- assertEquals("Markers should match", initialMarker, retrievedMarker);
- }
-
- @Test
- public void testGetAnnotations() {
- assertNotNull("Annotations should be non null", mMapboxMap.getAnnotations());
- }
-
- @Test
- public void testGetMarkers() {
- assertNotNull("Markers should be non null", mMapboxMap.getMarkers());
- }
-
- @Test
- public void testGetPolygons() {
- assertNotNull("Polygons should be non null", mMapboxMap.getPolygons());
- }
-
- @Test
- public void testGetPolylines() {
- assertNotNull("Polylines should be non null", mMapboxMap.getPolylines());
- }
-
- @Test
- public void testGetSelectedMarkers() {
- assertNotNull("Selected markers should be non null", mMapboxMap.getSelectedMarkers());
- }
-
- @Test
- public void testSelectMarker() {
- mMapboxMap.setOnMarkerClickListener(mOnMarkerClickListener);
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker marker = mMapboxMap.addMarker(markerOptions);
- when(mOnMarkerClickListener.onMarkerClick(marker)).thenReturn(true);
- mMapboxMap.selectMarker(marker);
- assertTrue("Marker should be contained", mMapboxMap.getSelectedMarkers().contains(marker));
- }
-
- @Test
- public void testDeselectMarker() {
- mMapboxMap.setOnMarkerClickListener(mOnMarkerClickListener);
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker marker = mMapboxMap.addMarker(markerOptions);
- when(mOnMarkerClickListener.onMarkerClick(marker)).thenReturn(true);
- mMapboxMap.selectMarker(marker);
- mMapboxMap.deselectMarker(marker);
- assertTrue("Selected markers should be empty", mMapboxMap.getSelectedMarkers().isEmpty());
- }
-
- @Test
- public void testDeselectMarkers() {
- mMapboxMap.setOnMarkerClickListener(mOnMarkerClickListener);
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker marker1 = mMapboxMap.addMarker(markerOptions);
- Marker marker2 = mMapboxMap.addMarker(markerOptions);
- when(mOnMarkerClickListener.onMarkerClick(marker1)).thenReturn(true);
- when(mOnMarkerClickListener.onMarkerClick(marker2)).thenReturn(true);
- mMapboxMap.selectMarker(marker1);
- mMapboxMap.selectMarker(marker2);
- mMapboxMap.deselectMarkers();
- assertTrue("Selected markers should be empty", mMapboxMap.getSelectedMarkers().isEmpty());
- }
-
- //
- // OnMarkerClick interface
- //
-
- @Test
- public void testOnMarkerClick() {
- mMapboxMap.setOnMarkerClickListener(mOnMarkerClickListener);
- Marker marker = new MarkerOptions().position(new LatLng()).getMarker();
- when(mOnMarkerClickListener.onMarkerClick(marker)).thenReturn(true);
- mMapboxMap.selectMarker(marker);
- verify(mOnMarkerClickListener, times(1)).onMarkerClick(marker);
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/ProjectionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/ProjectionTest.java
deleted file mode 100644
index fac06de16b..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/ProjectionTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.mapbox.mapboxsdk.maps;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.InjectMocks;
-import org.mockito.MockitoAnnotations;
-
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.mock;
-
-public class ProjectionTest {
-
- @InjectMocks
- MapView mMapView = mock(MapView.class);
-
- @Before
- public void beforeTest() {
- MockitoAnnotations.initMocks(this);
- }
-
- @Test
- public void testSanity() {
- Projection projection = new Projection(mMapView);
- assertNotNull("projection should not be null", projection);
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/TrackingSettingsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/TrackingSettingsTest.java
index 266bbadd95..57f3b942af 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/TrackingSettingsTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/TrackingSettingsTest.java
@@ -1,53 +1,70 @@
package com.mapbox.mapboxsdk.maps;
-import com.mapbox.mapboxsdk.constants.MyBearingTracking;
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+
import com.mapbox.mapboxsdk.constants.MyLocationTracking;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
+import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class TrackingSettingsTest {
- @InjectMocks
- MapView mMapView = mock(MapView.class);
-
- @Test
- public void testSanity() {
- TrackingSettings trackingSettings = new TrackingSettings(mMapView, new UiSettings(mMapView));
- assertNotNull("trackingsettings should not be null", trackingSettings);
- }
-
- @Test
- public void testMyLocationTrackingMode() {
- TrackingSettings trackingSettings = new TrackingSettings(mMapView, new UiSettings(mMapView));
- trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- assertEquals("MyLocationTrackingMode should match", MyLocationTracking.TRACKING_FOLLOW, trackingSettings.getMyLocationTrackingMode());
- }
-
- @Test
- public void testMyBearingTrackingMode() {
- TrackingSettings trackingSettings = new TrackingSettings(mMapView, new UiSettings(mMapView));
- trackingSettings.setMyBearingTrackingMode(MyBearingTracking.COMPASS);
- assertEquals("MyLocationTrackingMode should match", MyBearingTracking.COMPASS, trackingSettings.getMyBearingTrackingMode());
- }
-
- @Test
- public void testDismissTrackingModesOnGesture() {
- TrackingSettings trackingSettings = new TrackingSettings(mMapView, new UiSettings(mMapView));
- trackingSettings.setDismissTrackingOnGesture(false);
- assertFalse("DismissTrackingOnGesture should be false", trackingSettings.isDismissTrackingOnGesture());
- }
-
- @Test
- public void testValidateGesturesForTrackingModes(){
- TrackingSettings trackingSettings = new TrackingSettings(mMapView, new UiSettings(mMapView));
- trackingSettings.setDismissTrackingOnGesture(false);
- trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- assertFalse("DismissTrackingOnGesture should be false", trackingSettings.isDismissTrackingOnGesture());
- }
+ @InjectMocks
+ MyLocationView myLocationView = mock(MyLocationView.class);
+
+ @InjectMocks
+ UiSettings uiSettings = mock(UiSettings.class);
+
+ @InjectMocks
+ FocalPointChangeListener focalPointChangeListener = mock(FocalPointChangeListener.class);
+
+ private TrackingSettings trackingSettings;
+
+ @Before
+ public void beforeTest() {
+ trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPointChangeListener);
+ }
+
+ @Test
+ public void testSanity() {
+ assertNotNull("trackingsettings should not be null", trackingSettings);
+ }
+
+ @Test
+ public void testDismissTrackingModesOnGesture() {
+ trackingSettings.setDismissTrackingOnGesture(false);
+ assertFalse("DismissTrackingOnGesture should be false", trackingSettings.isDismissTrackingOnGesture());
+ }
+
+ @Test
+ public void testValidateGesturesForTrackingModes() {
+ trackingSettings.setDismissTrackingOnGesture(false);
+ trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
+ assertFalse("DismissTrackingOnGesture should be false", trackingSettings.isDismissTrackingOnGesture());
+ }
+
+ @Test
+ public void testMyLocationEnabled() {
+ // setup mock context to provide accepted location permission
+ Context context = mock(Context.class);
+ when(myLocationView.getContext()).thenReturn(context);
+ when(context.checkPermission(eq(Manifest.permission.ACCESS_COARSE_LOCATION), anyInt(),
+ anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
+
+ assertFalse("Location should be disabled by default.", trackingSettings.isMyLocationEnabled());
+ trackingSettings.setMyLocationEnabled(true);
+ assertTrue("Location should be enabled", trackingSettings.isMyLocationEnabled());
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
index 14fc84723d..1f532255d7 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
@@ -1,6 +1,11 @@
package com.mapbox.mapboxsdk.maps;
import android.view.Gravity;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.mapbox.mapboxsdk.maps.widgets.CompassView;
import org.junit.Before;
import org.junit.Test;
@@ -15,293 +20,321 @@ import static org.mockito.Mockito.when;
public class UiSettingsTest {
- @InjectMocks
- MapView mMapView = mock(MapView.class);
-
- UiSettings uiSettings;
-
- @Before
- public void beforeTest() {
- uiSettings = new UiSettings(mMapView);
- }
-
- @Test
- public void testSanity() {
- assertNotNull("uiSettings should not be null", uiSettings);
- }
-
- @Test
- public void testCompassEnabled() {
- uiSettings.setCompassEnabled(true);
- assertEquals("Compass should be enabled", true, uiSettings.isCompassEnabled());
- }
-
- @Test
- public void testCompassDisabled() {
- uiSettings.setCompassEnabled(false);
- assertEquals("Compass should be disabled", false, uiSettings.isCompassEnabled());
- }
-
- @Test
- public void testCompassGravity() {
- uiSettings.setCompassGravity(Gravity.LEFT);
- assertEquals("Compass gravity should be same", Gravity.LEFT, uiSettings.getCompassGravity());
- }
-
- @Test
- public void testCompassMargins() {
- uiSettings.setCompassMargins(1, 2, 3, 4);
- assertTrue("Compass margin left should be same", uiSettings.getCompassMarginLeft() == 1);
- assertTrue("Compass margin top should be same", uiSettings.getCompassMarginTop() == 2);
- assertTrue("Compass margin right should be same", uiSettings.getCompassMarginRight() == 3);
- assertTrue("Compass margin bottom should be same", uiSettings.getCompassMarginBottom() == 4);
- }
-
- @Test
- public void testCompassFadeWhenFacingNorth(){
- assertTrue("Compass should fade when facing north by default.", uiSettings.isCompassFadeWhenFacingNorth());
- uiSettings.setCompassFadeFacingNorth(false);
- assertFalse("Compass fading should be disabled", uiSettings.isCompassFadeWhenFacingNorth());
- }
-
- @Test
- public void testLogoEnabled() {
- uiSettings.setLogoEnabled(true);
- assertEquals("Logo should be enabled", true, uiSettings.isLogoEnabled());
- }
-
- @Test
- public void testLogoDisabled() {
- uiSettings.setLogoEnabled(false);
- assertEquals("Logo should be disabled", false, uiSettings.isLogoEnabled());
- }
-
- @Test
- public void testLogoGravity() {
- uiSettings.setLogoGravity(Gravity.RIGHT);
- assertEquals("Logo gravity should be same", Gravity.RIGHT, uiSettings.getLogoGravity());
- }
-
- @Test
- public void testLogoMargins() {
- uiSettings.setLogoMargins(1, 2, 3, 4);
- assertTrue("Compass margin left should be same", uiSettings.getLogoMarginLeft() == 1);
- assertTrue("Compass margin top should be same", uiSettings.getLogoMarginTop() == 2);
- assertTrue("Compass margin right should be same", uiSettings.getLogoMarginRight() == 3);
- assertTrue("Compass margin bottom should be same", uiSettings.getLogoMarginBottom() == 4);
- }
-
- @Test
- public void testAttributionEnabled() {
- uiSettings.setAttributionEnabled(true);
- assertEquals("Attribution should be enabled", true, uiSettings.isAttributionEnabled());
- }
-
- @Test
- public void testAttributionDisabled() {
- uiSettings.setAttributionEnabled(false);
- assertEquals("Attribution should be disabled", false, uiSettings.isLogoEnabled());
- }
-
- @Test
- public void testAttributionGravity() {
- uiSettings.setAttributionGravity(Gravity.RIGHT);
- assertEquals("Attribution gravity should be same", Gravity.RIGHT, uiSettings.getAttributionGravity());
- }
-
- @Test
- public void testAttributionMargins() {
- uiSettings.setAttributionMargins(1, 2, 3, 4);
- assertTrue("Attribution margin left should be same", uiSettings.getAttributionMarginLeft() == 1);
- assertTrue("Attribution margin top should be same", uiSettings.getAttributionMarginTop() == 2);
- assertTrue("Attribution margin right should be same", uiSettings.getAttributionMarginRight() == 3);
- assertTrue("Attribution margin bottom should be same", uiSettings.getAttributionMarginBottom() == 4);
- }
-
- @Test
- public void testRotateGesturesEnabled() {
- uiSettings.setRotateGesturesEnabled(true);
- assertEquals("Rotate gesture should be enabled", true, uiSettings.isRotateGesturesEnabled());
- }
-
- @Test
- public void testRotateGesturesDisabled() {
- uiSettings.setRotateGesturesEnabled(false);
- assertEquals("Rotate gesture should be disabled", false, uiSettings.isRotateGesturesEnabled());
- }
-
- @Test
- public void testRotateGestureChange() {
- assertEquals("Default state should be true", true, uiSettings.isRotateGestureChangeAllowed());
- uiSettings.setRotateGestureChangeAllowed(false);
- assertEquals("State should have been changed", false, uiSettings.isRotateGestureChangeAllowed());
- }
-
- @Test
- public void testRotateGestureChangeAllowed() {
- uiSettings.setRotateGesturesEnabled(false);
- assertEquals("Rotate gesture should be false", false, uiSettings.isRotateGesturesEnabled());
- uiSettings.setRotateGesturesEnabled(true);
- assertEquals("Rotate gesture should be true", true, uiSettings.isRotateGesturesEnabled());
- }
-
- @Test
- public void testRotateGestureChangeDisallowed() {
- assertEquals("Rotate gesture should be true", true, uiSettings.isRotateGesturesEnabled());
- uiSettings.setRotateGestureChangeAllowed(false);
- uiSettings.setRotateGesturesEnabled(false);
- assertEquals("Rotate gesture change should be ignored", true, uiSettings.isRotateGesturesEnabled());
- }
-
- @Test
- public void testTiltGesturesEnabled() {
- uiSettings.setTiltGesturesEnabled(true);
- assertEquals("Tilt gesture should be enabled", true, uiSettings.isTiltGesturesEnabled());
- }
-
- @Test
- public void testTiltGesturesDisabled() {
- uiSettings.setTiltGesturesEnabled(false);
- assertEquals("Tilt gesture should be disabled", false, uiSettings.isTiltGesturesEnabled());
- }
-
- @Test
- public void testTiltGestureChange() {
- assertEquals("Default state should be true", true, uiSettings.isTiltGestureChangeAllowed());
- uiSettings.setTiltGestureChangeAllowed(false);
- assertEquals("State should have been changed", false, uiSettings.isTiltGestureChangeAllowed());
- }
-
- @Test
- public void testTiltGestureChangeAllowed() {
- uiSettings.setTiltGesturesEnabled(false);
- assertEquals("Tilt gesture should be false", false, uiSettings.isTiltGesturesEnabled());
- uiSettings.setTiltGesturesEnabled(true);
- assertEquals("Tilt gesture should be true", true, uiSettings.isTiltGesturesEnabled());
- }
-
- @Test
- public void testTiltGestureChangeDisallowed() {
- assertEquals("Tilt gesture should be true", true, uiSettings.isTiltGesturesEnabled());
- uiSettings.setTiltGestureChangeAllowed(false);
- uiSettings.setTiltGesturesEnabled(false);
- assertEquals("Tilt gesture change should be ignored", true, uiSettings.isTiltGesturesEnabled());
- }
-
- @Test
- public void testZoomGesturesEnabled() {
- uiSettings.setZoomGesturesEnabled(true);
- assertEquals("Zoom gesture should be enabled", true, uiSettings.isZoomGesturesEnabled());
- }
-
- @Test
- public void testZoomGesturesDisabled() {
- uiSettings.setZoomGesturesEnabled(false);
- assertEquals("Zoom gesture should be disabled", false, uiSettings.isZoomGesturesEnabled());
- }
-
- @Test
- public void testZoomGestureChange() {
- assertEquals("Default state should be true", true, uiSettings.isZoomGestureChangeAllowed());
- uiSettings.setZoomGestureChangeAllowed(false);
- assertEquals("State should have been changed", false, uiSettings.isZoomGestureChangeAllowed());
- }
-
- @Test
- public void testZoomGestureChangeAllowed() {
- uiSettings.setZoomGesturesEnabled(false);
- assertEquals("Zoom gesture should be false", false, uiSettings.isZoomGesturesEnabled());
- uiSettings.setZoomGesturesEnabled(true);
- assertEquals("Zoom gesture should be true", true, uiSettings.isZoomGesturesEnabled());
- }
-
- @Test
- public void testZoomGestureChangeDisallowed() {
- assertEquals("Zoom gesture should be true", true, uiSettings.isZoomGesturesEnabled());
- uiSettings.setZoomGestureChangeAllowed(false);
- uiSettings.setZoomGesturesEnabled(false);
- assertEquals("Zooom gesture change should be ignored", true, uiSettings.isZoomGesturesEnabled());
- }
-
- @Test
- public void testZoomControlsEnabled() {
- uiSettings.setZoomControlsEnabled(true);
- assertEquals("Zoom controls should be enabled", true, uiSettings.isZoomControlsEnabled());
- }
-
- @Test
- public void testZoomControlsDisabled() {
- uiSettings.setZoomControlsEnabled(false);
- assertEquals("Zoom controls should be disabled", false, uiSettings.isZoomControlsEnabled());
- }
-
- @Test
- public void testScrollGesturesEnabled() {
- uiSettings.setScrollGesturesEnabled(true);
- assertEquals("Scroll gesture should be enabled", true, uiSettings.isScrollGesturesEnabled());
- }
-
- @Test
- public void testScrollGesturesDisabled() {
- uiSettings.setScrollGesturesEnabled(false);
- assertEquals("Scroll gesture should be disabled", false, uiSettings.isScrollGesturesEnabled());
- }
-
- @Test
- public void testScrollGestureChange() {
- assertEquals("Default state should be true", true, uiSettings.isScrollGestureChangeAllowed());
- uiSettings.setScrollGestureChangeAllowed(false);
- assertEquals("State should have been changed", false, uiSettings.isScrollGestureChangeAllowed());
- }
-
- @Test
- public void testScrollGestureChangeAllowed() {
- uiSettings.setScrollGesturesEnabled(false);
- assertEquals("Scroll gesture should be false", false, uiSettings.isScrollGesturesEnabled());
- uiSettings.setScrollGesturesEnabled(true);
- assertEquals("Scroll gesture should be true", true, uiSettings.isScrollGesturesEnabled());
- }
-
- @Test
- public void testScrollGestureChangeDisallowed() {
- assertEquals("Scroll gesture should be true", true, uiSettings.isScrollGesturesEnabled());
- uiSettings.setScrollGestureChangeAllowed(false);
- uiSettings.setScrollGesturesEnabled(false);
- assertEquals("Scroll gesture change should be ignored", true, uiSettings.isScrollGesturesEnabled());
- }
-
- @Test
- public void testAllGesturesEnabled() {
- uiSettings.setAllGesturesEnabled(true);
- assertEquals("Rotate gesture should be enabled", true, uiSettings.isRotateGesturesEnabled());
- assertEquals("Tilt gesture should be enabled", true, uiSettings.isTiltGesturesEnabled());
- assertEquals("Zoom gesture should be enabled", true, uiSettings.isZoomGesturesEnabled());
- assertEquals("Scroll gesture should be enabled", true, uiSettings.isScrollGesturesEnabled());
- }
-
- @Test
- public void testAllGesturesDisabled() {
- uiSettings.setAllGesturesEnabled(false);
- assertEquals("Rotate gesture should be enabled", false, uiSettings.isRotateGesturesEnabled());
- assertEquals("Tilt gesture should be disabled", false, uiSettings.isTiltGesturesEnabled());
- assertEquals("Zoom gesture should be disabled", false, uiSettings.isZoomGesturesEnabled());
- assertEquals("Scroll gesture should be disabled", false, uiSettings.isScrollGesturesEnabled());
- }
-
- @Test
- public void testInvalidate() {
- uiSettings.invalidate();
- }
-
- @Test
- public void testHeight() {
- when(mMapView.getMeasuredHeight()).thenReturn(1);
- assertEquals("height should be same as mocked instance", 1, uiSettings.getHeight(), 0);
- }
-
- @Test
- public void testWidth() {
- when(mMapView.getMeasuredWidth()).thenReturn(1);
- assertEquals("width should be same as mocked instance", 1, uiSettings.getWidth(), 0);
- }
+ @InjectMocks
+ Projection projection = mock(Projection.class);
+
+ @InjectMocks
+ FocalPointChangeListener focalPointChangeListener = mock(FocalPointChangeListener.class);
+
+ @InjectMocks
+ CompassView compassView = mock(CompassView.class);
+
+ @InjectMocks
+ ImageView imageView = mock(ImageView.class);
+
+ @InjectMocks
+ ImageView logoView = mock(ImageView.class);
+
+ @InjectMocks
+ FrameLayout.LayoutParams layoutParams = mock(FrameLayout.LayoutParams.class);
+
+ private UiSettings uiSettings;
+
+ @Before
+ public void beforeTest() {
+ uiSettings = new UiSettings(projection, focalPointChangeListener, compassView, imageView, logoView);
+ }
+
+ @Test
+ public void testSanity() {
+ assertNotNull("uiSettings should not be null", uiSettings);
+ }
+
+ @Test
+ public void testCompassEnabled() {
+ when(compassView.isEnabled()).thenReturn(true);
+ uiSettings.setCompassEnabled(true);
+ assertEquals("Compass should be enabled", true, uiSettings.isCompassEnabled());
+ }
+
+ @Test
+ public void testCompassDisabled() {
+ uiSettings.setCompassEnabled(false);
+ assertEquals("Compass should be disabled", false, uiSettings.isCompassEnabled());
+ }
+
+ @Test
+ public void testCompassGravity() {
+ when(compassView.getLayoutParams()).thenReturn(layoutParams);
+ layoutParams.gravity = Gravity.START;
+ uiSettings.setCompassGravity(Gravity.START);
+ assertEquals("Compass gravity should be same", Gravity.START, uiSettings.getCompassGravity());
+ }
+
+ @Test
+ public void testCompassMargins() {
+ when(projection.getContentPadding()).thenReturn(new int[] {0, 0, 0, 0});
+ when(compassView.getLayoutParams()).thenReturn(layoutParams);
+ layoutParams.leftMargin = 1;
+ layoutParams.topMargin = 2;
+ layoutParams.rightMargin = 3;
+ layoutParams.bottomMargin = 4;
+ uiSettings.setCompassMargins(1, 2, 3, 4);
+ assertTrue("Compass margin left should be same", uiSettings.getCompassMarginLeft() == 1);
+ assertTrue("Compass margin top should be same", uiSettings.getCompassMarginTop() == 2);
+ assertTrue("Compass margin right should be same", uiSettings.getCompassMarginRight() == 3);
+ assertTrue("Compass margin bottom should be same", uiSettings.getCompassMarginBottom() == 4);
+ }
+
+ @Test
+ public void testCompassFadeWhenFacingNorth() {
+ when(compassView.isFadeCompassViewFacingNorth()).thenReturn(true);
+ assertTrue("Compass should fade when facing north by default.", uiSettings.isCompassFadeWhenFacingNorth());
+ uiSettings.setCompassFadeFacingNorth(false);
+ when(compassView.isFadeCompassViewFacingNorth()).thenReturn(false);
+ assertFalse("Compass fading should be disabled", uiSettings.isCompassFadeWhenFacingNorth());
+ }
+
+ @Test
+ public void testLogoEnabled() {
+ uiSettings.setLogoEnabled(true);
+ assertEquals("Logo should be enabled", true, uiSettings.isLogoEnabled());
+ }
+
+ @Test
+ public void testLogoDisabled() {
+ when(logoView.getVisibility()).thenReturn(View.GONE);
+ uiSettings.setLogoEnabled(false);
+ assertEquals("Logo should be disabled", false, uiSettings.isLogoEnabled());
+ }
+
+ @Test
+ public void testLogoGravity() {
+ layoutParams.gravity = Gravity.END;
+ when(logoView.getLayoutParams()).thenReturn(layoutParams);
+ uiSettings.setLogoGravity(Gravity.END);
+ assertEquals("Logo gravity should be same", Gravity.END, uiSettings.getLogoGravity());
+ }
+
+ @Test
+ public void testLogoMargins() {
+ when(projection.getContentPadding()).thenReturn(new int[] {0, 0, 0, 0});
+ when(logoView.getLayoutParams()).thenReturn(layoutParams);
+ layoutParams.leftMargin = 1;
+ layoutParams.topMargin = 2;
+ layoutParams.rightMargin = 3;
+ layoutParams.bottomMargin = 4;
+ uiSettings.setLogoMargins(1, 2, 3, 4);
+ assertTrue("Compass margin left should be same", uiSettings.getLogoMarginLeft() == 1);
+ assertTrue("Compass margin top should be same", uiSettings.getLogoMarginTop() == 2);
+ assertTrue("Compass margin right should be same", uiSettings.getLogoMarginRight() == 3);
+ assertTrue("Compass margin bottom should be same", uiSettings.getLogoMarginBottom() == 4);
+ }
+
+ @Test
+ public void testAttributionEnabled() {
+ when(imageView.getVisibility()).thenReturn(View.VISIBLE);
+ uiSettings.setAttributionEnabled(true);
+ assertEquals("Attribution should be enabled", true, uiSettings.isAttributionEnabled());
+ }
+
+ @Test
+ public void testAttributionDisabled() {
+ when(imageView.getVisibility()).thenReturn(View.GONE);
+ uiSettings.setAttributionEnabled(false);
+ assertEquals("Attribution should be disabled", false, uiSettings.isAttributionEnabled());
+ }
+
+ @Test
+ public void testAttributionGravity() {
+ when(imageView.getLayoutParams()).thenReturn(layoutParams);
+ layoutParams.gravity = Gravity.END;
+ uiSettings.setAttributionGravity(Gravity.END);
+ assertEquals("Attribution gravity should be same", Gravity.END, uiSettings.getAttributionGravity());
+ }
+
+ @Test
+ public void testAttributionMargins() {
+ when(imageView.getLayoutParams()).thenReturn(layoutParams);
+ when(projection.getContentPadding()).thenReturn(new int[] {0, 0, 0, 0});
+ layoutParams.leftMargin = 1;
+ layoutParams.topMargin = 2;
+ layoutParams.rightMargin = 3;
+ layoutParams.bottomMargin = 4;
+ uiSettings.setAttributionMargins(1, 2, 3, 4);
+ assertTrue("Attribution margin left should be same", uiSettings.getAttributionMarginLeft() == 1);
+ assertTrue("Attribution margin top should be same", uiSettings.getAttributionMarginTop() == 2);
+ assertTrue("Attribution margin right should be same", uiSettings.getAttributionMarginRight() == 3);
+ assertTrue("Attribution margin bottom should be same", uiSettings.getAttributionMarginBottom() == 4);
+ }
+
+ @Test
+ public void testRotateGesturesEnabled() {
+ uiSettings.setRotateGesturesEnabled(true);
+ assertEquals("Rotate gesture should be enabled", true, uiSettings.isRotateGesturesEnabled());
+ }
+
+ @Test
+ public void testRotateGesturesDisabled() {
+ uiSettings.setRotateGesturesEnabled(false);
+ assertEquals("Rotate gesture should be disabled", false, uiSettings.isRotateGesturesEnabled());
+ }
+
+ @Test
+ public void testRotateGestureChange() {
+ assertEquals("Default state should be true", true, uiSettings.isRotateGestureChangeAllowed());
+ uiSettings.setRotateGestureChangeAllowed(false);
+ assertEquals("State should have been changed", false, uiSettings.isRotateGestureChangeAllowed());
+ }
+
+ @Test
+ public void testRotateGestureChangeAllowed() {
+ uiSettings.setRotateGesturesEnabled(false);
+ assertEquals("Rotate gesture should be false", false, uiSettings.isRotateGesturesEnabled());
+ uiSettings.setRotateGesturesEnabled(true);
+ assertEquals("Rotate gesture should be true", true, uiSettings.isRotateGesturesEnabled());
+ }
+
+ @Test
+ public void testRotateGestureChangeDisallowed() {
+ assertEquals("Rotate gesture should be true", true, uiSettings.isRotateGesturesEnabled());
+ uiSettings.setRotateGestureChangeAllowed(false);
+ uiSettings.setRotateGesturesEnabled(false);
+ assertEquals("Rotate gesture change should be ignored", true, uiSettings.isRotateGesturesEnabled());
+ }
+
+ @Test
+ public void testTiltGesturesEnabled() {
+ uiSettings.setTiltGesturesEnabled(true);
+ assertEquals("Tilt gesture should be enabled", true, uiSettings.isTiltGesturesEnabled());
+ }
+
+ @Test
+ public void testTiltGesturesDisabled() {
+ uiSettings.setTiltGesturesEnabled(false);
+ assertEquals("Tilt gesture should be disabled", false, uiSettings.isTiltGesturesEnabled());
+ }
+
+ @Test
+ public void testTiltGestureChange() {
+ assertEquals("Default state should be true", true, uiSettings.isTiltGestureChangeAllowed());
+ uiSettings.setTiltGestureChangeAllowed(false);
+ assertEquals("State should have been changed", false, uiSettings.isTiltGestureChangeAllowed());
+ }
+
+ @Test
+ public void testTiltGestureChangeAllowed() {
+ uiSettings.setTiltGesturesEnabled(false);
+ assertEquals("Tilt gesture should be false", false, uiSettings.isTiltGesturesEnabled());
+ uiSettings.setTiltGesturesEnabled(true);
+ assertEquals("Tilt gesture should be true", true, uiSettings.isTiltGesturesEnabled());
+ }
+
+ @Test
+ public void testTiltGestureChangeDisallowed() {
+ assertEquals("Tilt gesture should be true", true, uiSettings.isTiltGesturesEnabled());
+ uiSettings.setTiltGestureChangeAllowed(false);
+ uiSettings.setTiltGesturesEnabled(false);
+ assertEquals("Tilt gesture change should be ignored", true, uiSettings.isTiltGesturesEnabled());
+ }
+
+ @Test
+ public void testZoomGesturesEnabled() {
+ uiSettings.setZoomGesturesEnabled(true);
+ assertEquals("Zoom gesture should be enabled", true, uiSettings.isZoomGesturesEnabled());
+ }
+
+ @Test
+ public void testZoomGesturesDisabled() {
+ uiSettings.setZoomGesturesEnabled(false);
+ assertEquals("Zoom gesture should be disabled", false, uiSettings.isZoomGesturesEnabled());
+ }
+
+ @Test
+ public void testZoomGestureChange() {
+ assertEquals("Default state should be true", true, uiSettings.isZoomGestureChangeAllowed());
+ uiSettings.setZoomGestureChangeAllowed(false);
+ assertEquals("State should have been changed", false, uiSettings.isZoomGestureChangeAllowed());
+ }
+
+ @Test
+ public void testZoomGestureChangeAllowed() {
+ uiSettings.setZoomGesturesEnabled(false);
+ assertEquals("Zoom gesture should be false", false, uiSettings.isZoomGesturesEnabled());
+ uiSettings.setZoomGesturesEnabled(true);
+ assertEquals("Zoom gesture should be true", true, uiSettings.isZoomGesturesEnabled());
+ }
+
+ @Test
+ public void testZoomGestureChangeDisallowed() {
+ assertEquals("Zoom gesture should be true", true, uiSettings.isZoomGesturesEnabled());
+ uiSettings.setZoomGestureChangeAllowed(false);
+ uiSettings.setZoomGesturesEnabled(false);
+ assertEquals("Zooom gesture change should be ignored", true, uiSettings.isZoomGesturesEnabled());
+ }
+
+ @Test
+ public void testZoomControlsEnabled() {
+ uiSettings.setZoomControlsEnabled(true);
+ assertEquals("Zoom controls should be enabled", true, uiSettings.isZoomControlsEnabled());
+ }
+
+ @Test
+ public void testZoomControlsDisabled() {
+ uiSettings.setZoomControlsEnabled(false);
+ assertEquals("Zoom controls should be disabled", false, uiSettings.isZoomControlsEnabled());
+ }
+
+ @Test
+ public void testScrollGesturesEnabled() {
+ uiSettings.setScrollGesturesEnabled(true);
+ assertEquals("Scroll gesture should be enabled", true, uiSettings.isScrollGesturesEnabled());
+ }
+
+ @Test
+ public void testScrollGesturesDisabled() {
+ uiSettings.setScrollGesturesEnabled(false);
+ assertEquals("Scroll gesture should be disabled", false, uiSettings.isScrollGesturesEnabled());
+ }
+
+ @Test
+ public void testScrollGestureChange() {
+ assertEquals("Default state should be true", true, uiSettings.isScrollGestureChangeAllowed());
+ uiSettings.setScrollGestureChangeAllowed(false);
+ assertEquals("State should have been changed", false, uiSettings.isScrollGestureChangeAllowed());
+ }
+
+ @Test
+ public void testScrollGestureChangeAllowed() {
+ uiSettings.setScrollGesturesEnabled(false);
+ assertEquals("Scroll gesture should be false", false, uiSettings.isScrollGesturesEnabled());
+ uiSettings.setScrollGesturesEnabled(true);
+ assertEquals("Scroll gesture should be true", true, uiSettings.isScrollGesturesEnabled());
+ }
+
+ @Test
+ public void testScrollGestureChangeDisallowed() {
+ assertEquals("Scroll gesture should be true", true, uiSettings.isScrollGesturesEnabled());
+ uiSettings.setScrollGestureChangeAllowed(false);
+ uiSettings.setScrollGesturesEnabled(false);
+ assertEquals("Scroll gesture change should be ignored", true, uiSettings.isScrollGesturesEnabled());
+ }
+
+ @Test
+ public void testAllGesturesEnabled() {
+ uiSettings.setAllGesturesEnabled(true);
+ assertEquals("Rotate gesture should be enabled", true, uiSettings.isRotateGesturesEnabled());
+ assertEquals("Tilt gesture should be enabled", true, uiSettings.isTiltGesturesEnabled());
+ assertEquals("Zoom gesture should be enabled", true, uiSettings.isZoomGesturesEnabled());
+ assertEquals("Scroll gesture should be enabled", true, uiSettings.isScrollGesturesEnabled());
+ }
+
+ @Test
+ public void testAllGesturesDisabled() {
+ uiSettings.setAllGesturesEnabled(false);
+ assertEquals("Rotate gesture should be enabled", false, uiSettings.isRotateGesturesEnabled());
+ assertEquals("Tilt gesture should be disabled", false, uiSettings.isTiltGesturesEnabled());
+ assertEquals("Zoom gesture should be disabled", false, uiSettings.isZoomGesturesEnabled());
+ assertEquals("Scroll gesture should be disabled", false, uiSettings.isScrollGesturesEnabled());
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java
index fd70308931..c9ce19dc85 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java
@@ -3,7 +3,9 @@ package com.mapbox.mapboxsdk.maps.widgets;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
-import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.FocalPointChangeListener;
+import com.mapbox.mapboxsdk.maps.Projection;
+import com.mapbox.mapboxsdk.maps.TrackingSettings;
import org.junit.Before;
import org.junit.Test;
@@ -20,64 +22,85 @@ import static org.mockito.Mockito.when;
public class MyLocationViewSettingsTest {
- @InjectMocks
- MapView mMapView = mock(MapView.class);
-
- @InjectMocks
- MyLocationView myLocationView = mock(MyLocationView.class);
-
- MyLocationViewSettings locationViewSettings;
-
- @Before
- public void beforeTest() {
- locationViewSettings = new MyLocationViewSettings(mMapView, myLocationView);
- }
-
- @Test
- public void testSanity() {
- assertNotNull("should not be null", locationViewSettings);
- }
-
- @Test
- public void testForegroundDrawables() {
- Drawable foregroundDrawable = mock(Drawable.class);
- Drawable foregroundBearingDrawable = mock(Drawable.class);
- Drawable.ConstantState constantState = mock(Drawable.ConstantState.class);
- when(foregroundDrawable.getConstantState()).thenReturn(constantState);
- when(constantState.newDrawable()).thenReturn(foregroundDrawable);
- locationViewSettings.setForegroundDrawable(foregroundDrawable, foregroundBearingDrawable);
- assertEquals("foreground should match", foregroundDrawable, locationViewSettings.getForegroundDrawable());
- assertEquals("foreground bearing should match", foregroundBearingDrawable, locationViewSettings.getForegroundBearingDrawable());
- }
-
- @Test
- public void testBackgroundDrawable() {
- Drawable backgroundDrawable = mock(Drawable.class);
- int[] offset = new int[]{1, 2, 3, 4};
- locationViewSettings.setBackgroundDrawable(backgroundDrawable, offset);
- assertEquals("foreground should match", backgroundDrawable, locationViewSettings.getBackgroundDrawable());
- assertTrue("offsets should match", Arrays.equals(offset, locationViewSettings.getBackgroundOffset()));
- }
-
- @Test
- public void testForegroundTint() {
- int color = Color.RED;
- locationViewSettings.setForegroundTintColor(Color.RED);
- assertEquals("color should match", color, locationViewSettings.getForegroundTintColor());
- }
-
- @Test
- public void testBackgroundTint() {
- int color = Color.RED;
- locationViewSettings.setBackgroundTintColor(Color.RED);
- assertEquals("color should match", color, locationViewSettings.getBackgroundTintColor());
- }
-
- @Test
- public void testEnabled() {
- assertFalse("initial state should be false", locationViewSettings.isEnabled());
- locationViewSettings.setEnabled(true);
- assertTrue("state should be true", locationViewSettings.isEnabled());
- }
-
+ @InjectMocks
+ Projection projection = mock(Projection.class);
+
+ @InjectMocks
+ MyLocationView myLocationView = mock(MyLocationView.class);
+
+ @InjectMocks
+ TrackingSettings trackingSettings = mock(TrackingSettings.class);
+
+ @InjectMocks
+ FocalPointChangeListener focalPointChangeListener = mock(FocalPointChangeListener.class);
+
+ private MyLocationViewSettings locationViewSettings;
+
+ @Before
+ public void beforeTest() {
+ locationViewSettings = new MyLocationViewSettings(myLocationView, projection, focalPointChangeListener);
+ }
+
+ @Test
+ public void testSanity() {
+ assertNotNull("should not be null", locationViewSettings);
+ }
+
+ @Test
+ public void testForegroundDrawables() {
+ Drawable foregroundDrawable = mock(Drawable.class);
+ Drawable foregroundBearingDrawable = mock(Drawable.class);
+ Drawable.ConstantState constantState = mock(Drawable.ConstantState.class);
+ when(foregroundDrawable.getConstantState()).thenReturn(constantState);
+ when(constantState.newDrawable()).thenReturn(foregroundDrawable);
+ locationViewSettings.setForegroundDrawable(foregroundDrawable, foregroundBearingDrawable);
+ assertEquals("foreground should match", foregroundDrawable, locationViewSettings.getForegroundDrawable());
+ assertEquals("foreground bearing should match", foregroundBearingDrawable,
+ locationViewSettings.getForegroundBearingDrawable());
+ }
+
+ @Test
+ public void testBackgroundDrawable() {
+ Drawable backgroundDrawable = mock(Drawable.class);
+ int[] offset = new int[] {1, 2, 3, 4};
+ locationViewSettings.setBackgroundDrawable(backgroundDrawable, offset);
+ assertEquals("foreground should match", backgroundDrawable, locationViewSettings.getBackgroundDrawable());
+ assertTrue("offsets should match", Arrays.equals(offset, locationViewSettings.getBackgroundOffset()));
+ }
+
+ @Test
+ public void testForegroundTint() {
+ int color = Color.RED;
+ locationViewSettings.setForegroundTintColor(Color.RED);
+ assertEquals("color should match", color, locationViewSettings.getForegroundTintColor());
+ }
+
+ @Test
+ public void testForegroundTransparentTint() {
+ int color = Color.TRANSPARENT;
+ locationViewSettings.setForegroundTintColor(Color.TRANSPARENT);
+ assertEquals("color should match", color, locationViewSettings.getForegroundTintColor());
+ }
+
+ @Test
+ public void testBackgroundTint() {
+ int color = Color.RED;
+ locationViewSettings.setBackgroundTintColor(Color.RED);
+ assertEquals("color should match", color, locationViewSettings.getBackgroundTintColor());
+ }
+
+ @Test
+ public void testBackgroundTransparentTint() {
+ int color = Color.TRANSPARENT;
+ locationViewSettings.setBackgroundTintColor(Color.TRANSPARENT);
+ assertEquals("color should match", color, locationViewSettings.getBackgroundTintColor());
+ }
+
+ @Test
+ public void testEnabled() {
+ assertFalse("initial state should be false", locationViewSettings.isEnabled());
+ locationViewSettings.setEnabled(true);
+ assertTrue("state should be true", locationViewSettings.isEnabled());
+ }
}
+
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/style/layers/FilterTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/style/layers/FilterTest.java
index 3e312d3b0a..933bf05b39 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/style/layers/FilterTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/style/layers/FilterTest.java
@@ -2,89 +2,101 @@ package com.mapbox.mapboxsdk.style.layers;
import org.junit.Test;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Filter.*;
+import static com.mapbox.mapboxsdk.style.layers.Filter.all;
+import static com.mapbox.mapboxsdk.style.layers.Filter.any;
+import static com.mapbox.mapboxsdk.style.layers.Filter.eq;
+import static com.mapbox.mapboxsdk.style.layers.Filter.gt;
+import static com.mapbox.mapboxsdk.style.layers.Filter.gte;
+import static com.mapbox.mapboxsdk.style.layers.Filter.has;
+import static com.mapbox.mapboxsdk.style.layers.Filter.in;
+import static com.mapbox.mapboxsdk.style.layers.Filter.lt;
+import static com.mapbox.mapboxsdk.style.layers.Filter.lte;
+import static com.mapbox.mapboxsdk.style.layers.Filter.neq;
+import static com.mapbox.mapboxsdk.style.layers.Filter.none;
+import static com.mapbox.mapboxsdk.style.layers.Filter.notHas;
+import static com.mapbox.mapboxsdk.style.layers.Filter.notIn;
+import static org.junit.Assert.assertArrayEquals;
/**
* Tests for Filter
*/
public class FilterTest {
- @Test
- public void testAll() {
- assertArrayEquals(all().toArray(), new Object[]{"all"});
- assertArrayEquals(
- all(eq("key", 2), neq("key", 3)).toArray(),
- new Object[]{"all", new Object[]{"==", "key", 2}, new Object[]{"!=", "key", 3}}
- );
- }
-
- @Test
- public void testAny() {
- assertArrayEquals(any().toArray(), new Object[]{"any"});
- assertArrayEquals(
- any(eq("key", 2), neq("key", 3)).toArray(),
- new Object[]{"any", new Object[]{"==", "key", 2}, new Object[]{"!=", "key", 3}}
- );
- }
-
- @Test
- public void testNone() {
- assertArrayEquals(none().toArray(), new Object[]{"none"});
- assertArrayEquals(
- none(eq("key", 2), neq("key", 3)).toArray(),
- new Object[]{"none", new Object[]{"==", "key", 2}, new Object[]{"!=", "key", 3}}
- );
- }
-
- @Test
- public void testHas() {
- assertArrayEquals(has("key").toArray(), new Object[]{"has", "key"});
- }
-
- @Test
- public void testHasNot() {
- assertArrayEquals(notHas("key").toArray(), new Object[]{"!has", "key"});
- }
-
- @Test
- public void testEq() {
- assertArrayEquals(eq("key", 1).toArray(), new Object[]{"==", "key", 1});
-
- }
-
- @Test
- public void testNeq() {
- assertArrayEquals(neq("key", 1).toArray(), new Object[]{"!=", "key", 1});
- }
-
- @Test
- public void testGt() {
- assertArrayEquals(gt("key", 1).toArray(), new Object[]{">", "key", 1});
- }
-
- @Test
- public void testGte() {
- assertArrayEquals(gte("key", 1).toArray(), new Object[]{">=", "key", 1});
- }
-
- @Test
- public void testLt() {
- assertArrayEquals(lt("key", 1).toArray(), new Object[]{"<", "key", 1});
- }
-
- @Test
- public void testLte() {
- assertArrayEquals(lte("key", 1).toArray(), new Object[]{"<=", "key", 1});
- }
-
- @Test
- public void testIn() {
- assertArrayEquals(in("key", 1, 2, "Aap").toArray(), new Object[]{"in", "key", 1, 2, "Aap"});
- }
-
- @Test
- public void testNotIn() {
- assertArrayEquals(notIn("key", 1, 2, "Noot").toArray(), new Object[]{"!in", "key", 1, 2, "Noot"});
- }
+ @Test
+ public void testAll() {
+ assertArrayEquals(all().toArray(), new Object[] {"all"});
+ assertArrayEquals(
+ all(eq("key", 2), neq("key", 3)).toArray(),
+ new Object[] {"all", new Object[] {"==", "key", 2}, new Object[] {"!=", "key", 3}}
+ );
+ }
+
+ @Test
+ public void testAny() {
+ assertArrayEquals(any().toArray(), new Object[] {"any"});
+ assertArrayEquals(
+ any(eq("key", 2), neq("key", 3)).toArray(),
+ new Object[] {"any", new Object[] {"==", "key", 2}, new Object[] {"!=", "key", 3}}
+ );
+ }
+
+ @Test
+ public void testNone() {
+ assertArrayEquals(none().toArray(), new Object[] {"none"});
+ assertArrayEquals(
+ none(eq("key", 2), neq("key", 3)).toArray(),
+ new Object[] {"none", new Object[] {"==", "key", 2}, new Object[] {"!=", "key", 3}}
+ );
+ }
+
+ @Test
+ public void testHas() {
+ assertArrayEquals(has("key").toArray(), new Object[] {"has", "key"});
+ }
+
+ @Test
+ public void testHasNot() {
+ assertArrayEquals(notHas("key").toArray(), new Object[] {"!has", "key"});
+ }
+
+ @Test
+ public void testEq() {
+ assertArrayEquals(eq("key", 1).toArray(), new Object[] {"==", "key", 1});
+
+ }
+
+ @Test
+ public void testNeq() {
+ assertArrayEquals(neq("key", 1).toArray(), new Object[] {"!=", "key", 1});
+ }
+
+ @Test
+ public void testGt() {
+ assertArrayEquals(gt("key", 1).toArray(), new Object[] {">", "key", 1});
+ }
+
+ @Test
+ public void testGte() {
+ assertArrayEquals(gte("key", 1).toArray(), new Object[] {">=", "key", 1});
+ }
+
+ @Test
+ public void testLt() {
+ assertArrayEquals(lt("key", 1).toArray(), new Object[] {"<", "key", 1});
+ }
+
+ @Test
+ public void testLte() {
+ assertArrayEquals(lte("key", 1).toArray(), new Object[] {"<=", "key", 1});
+ }
+
+ @Test
+ public void testIn() {
+ assertArrayEquals(in("key", 1, 2, "Aap").toArray(), new Object[] {"in", "key", 1, 2, "Aap"});
+ }
+
+ @Test
+ public void testNotIn() {
+ assertArrayEquals(notIn("key", 1, 2, "Noot").toArray(), new Object[] {"!in", "key", 1, 2, "Noot"});
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/style/layers/FunctionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/style/layers/FunctionTest.java
index 1106009ea8..4e82ca2318 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/style/layers/FunctionTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/style/layers/FunctionTest.java
@@ -2,28 +2,29 @@ package com.mapbox.mapboxsdk.style.layers;
import org.junit.Test;
-import static com.mapbox.mapboxsdk.style.layers.Function.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
-
-import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Function.stop;
+import static com.mapbox.mapboxsdk.style.layers.Function.zoom;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineBlur;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Tests Function
*/
public class FunctionTest {
- @Test
- public void testZoomFunction() {
- Function zoomF = zoom(
- stop(1f, lineBlur(1f)),
- stop(10f, lineBlur(20f))
- );
+ @Test
+ public void testZoomFunction() {
+ Function zoomF = zoom(
+ stop(1f, lineBlur(1f)),
+ stop(10f, lineBlur(20f))
+ );
- assertNotNull(zoomF.toValueObject());
- assertArrayEquals(
- new Object[]{new Object[]{1f, 1f}, new Object[]{10f, 20f}},
- (Object[]) zoomF.toValueObject().get("stops")
- );
- }
+ assertNotNull(zoomF.toValueObject());
+ assertArrayEquals(
+ new Object[] {new Object[] {1f, 1f}, new Object[] {10f, 20f}},
+ (Object[]) zoomF.toValueObject().get("stops")
+ );
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/ExponentialBackOffTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/ExponentialBackOffTest.java
new file mode 100644
index 0000000000..50ce19c050
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/ExponentialBackOffTest.java
@@ -0,0 +1,19 @@
+package com.mapbox.mapboxsdk.telemetry;
+
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+
+public class ExponentialBackOffTest {
+
+ @Test
+ public void testExponentialBackOff() {
+ MapboxEventManager.ExponentialBackoffCounter counter = new MapboxEventManager.ExponentialBackoffCounter();
+ assertEquals(30000, counter.getNextCount());
+ assertEquals(60000, counter.getNextCount());
+ assertEquals(90000, counter.getNextCount());
+ assertEquals(120000, counter.getNextCount());
+ assertEquals(150000, counter.getNextCount());
+ assertEquals(180000, counter.getNextCount());
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java
index 8be0d2c663..94a6dc2194 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java
@@ -1,17 +1,20 @@
package com.mapbox.mapboxsdk.telemetry;
import org.junit.Test;
+
import okhttp3.internal.Util;
+
import static junit.framework.Assert.assertEquals;
public class HttpTransportTest {
- @Test
- public void testNonAsciiUserAgent() {
+ @Test
+ public void testNonAsciiUserAgent() {
- final String swedishUserAgent = "Sveriges Fjäll/1.0/1 MapboxEventsAndroid/4.0.0-SNAPSHOT";
- final String asciiVersion = "Sveriges Fj?ll/1.0/1 MapboxEventsAndroid/4.0.0-SNAPSHOT";
+ final String swedishUserAgent = "Sveriges Fjäll/1.0/1 MapboxEventsAndroid/4.0.0-SNAPSHOT";
+ final String asciiVersion = "Sveriges Fj?ll/1.0/1 MapboxEventsAndroid/4.0.0-SNAPSHOT";
- assertEquals("asciiVersion and swedishUserAgent should match", asciiVersion, Util.toHumanReadableAscii(swedishUserAgent));
- }
+ assertEquals("asciiVersion and swedishUserAgent should match", asciiVersion,
+ Util.toHumanReadableAscii(swedishUserAgent));
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/utils/MockParcel.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/utils/MockParcel.java
index aa0a4edd13..dd4c7b25ee 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/utils/MockParcel.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/utils/MockParcel.java
@@ -13,7 +13,6 @@ import java.util.ArrayList;
import java.util.List;
import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
import static org.junit.Assert.assertArrayEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyByte;
@@ -29,227 +28,227 @@ import static org.mockito.Mockito.when;
public class MockParcel {
- public static Parcelable obtain(@NonNull Parcelable object) {
- return obtain(object, 0);
+ public static Parcelable obtain(@NonNull Parcelable object) {
+ return obtain(object, 0);
+ }
+
+ public static Parcelable obtain(@NonNull Parcelable object, int describeContentsValue) {
+ testDescribeContents(object, describeContentsValue);
+ testParcelableArray(object);
+ return testParcelable(object);
+ }
+
+ public static Parcelable testParcelable(@NonNull Parcelable object) {
+ Parcel parcel = ParcelMocker.obtain(object);
+ object.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ try {
+ Field field = object.getClass().getDeclaredField("CREATOR");
+ field.setAccessible(true);
+ Class<?> creatorClass = field.getType();
+ Object fieldValue = field.get(object);
+ Method myMethod = creatorClass.getDeclaredMethod("createFromParcel", Parcel.class);
+ return (Parcelable) myMethod.invoke(fieldValue, parcel);
+ } catch (Exception exception) {
+ return null;
}
+ }
+
+ public static void testParcelableArray(@NonNull Parcelable object) {
+ Parcelable[] objects = new Parcelable[] {object};
+ Parcel parcel = ParcelMocker.obtain(objects);
+ parcel.writeParcelableArray(objects, 0);
+ parcel.setDataPosition(0);
+ Parcelable[] parcelableArray = parcel.readParcelableArray(object.getClass().getClassLoader());
+ assertArrayEquals("parcel should match initial object", objects, parcelableArray);
+ }
+
+ public static void testDescribeContents(@NonNull Parcelable object, int describeContentsValue) {
+ if (describeContentsValue == 0) {
+ assertEquals("\nExpecting a describeContents() value of 0 for a " + object.getClass().getSimpleName()
+ + " instance." + "\nYou can provide a different value for describeContentValue through the obtain method.",
+ 0,
+ object.describeContents());
+ } else {
+ assertEquals("Expecting a describeContents() value of " + describeContentsValue,
+ describeContentsValue,
+ object.describeContents());
+ }
+ }
+
+ private static class ParcelMocker {
- public static Parcelable obtain(@NonNull Parcelable object, int describeContentsValue) {
- testDescribeContents(object, describeContentsValue);
- testParcelableArray(object);
- return testParcelable(object);
+ public static Parcel obtain(@NonNull Parcelable target) {
+ Parcel parcel = new ParcelMocker(target).getMockedParcel();
+ target.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ return parcel;
}
- public static Parcelable testParcelable(@NonNull Parcelable object) {
- Parcel parcel = ParcelMocker.obtain(object);
- object.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
-
- try {
- Field field = object.getClass().getDeclaredField("CREATOR");
- field.setAccessible(true);
- Class<?> creatorClass = field.getType();
- Object fieldValue = field.get(object);
- Method myMethod = creatorClass.getDeclaredMethod("createFromParcel", Parcel.class);
- return (Parcelable) myMethod.invoke(fieldValue, parcel);
- } catch (Exception e) {
- return null;
- }
+ public static Parcel obtain(@NonNull Parcelable[] targets) {
+ if (targets.length == 0) {
+ throw new IllegalArgumentException("The passed argument may not be empty");
+ }
+ Parcel parcel = new ParcelMocker(targets[0]).getMockedParcel();
+ parcel.writeParcelableArray(targets, 0);
+ parcel.setDataPosition(0);
+ return parcel;
}
- public static void testParcelableArray(@NonNull Parcelable object) {
- Parcelable[] objects = new Parcelable[]{object};
- Parcel parcel = ParcelMocker.obtain(objects);
- parcel.writeParcelableArray(objects, 0);
- parcel.setDataPosition(0);
- Parcelable[] parcelableArray = parcel.readParcelableArray(object.getClass().getClassLoader());
- assertArrayEquals("parcel should match initial object", objects, parcelableArray);
+ private List<Object> objects;
+ private Object object;
+ private Parcel mockedParcel;
+ private int position;
+
+ private ParcelMocker(Object o) {
+ this.object = o;
+ mockedParcel = mock(Parcel.class);
+ objects = new ArrayList<>();
+ setupMock();
}
- public static void testDescribeContents(@NonNull Parcelable object, int describeContentsValue) {
- if (describeContentsValue == 0) {
- assertEquals("\nExpecting a describeContents() value of 0 for a " + object.getClass().getSimpleName() + " instance." +
- "\nYou can provide a different value for describeContentValue through the obtain method.",
- 0,
- object.describeContents());
- } else {
- assertEquals("Expecting a describeContents() value of " + describeContentsValue,
- describeContentsValue,
- object.describeContents());
- }
+ private Parcel getMockedParcel() {
+ return mockedParcel;
}
- private static class ParcelMocker {
+ private void setupMock() {
+ setupWrites();
+ setupReads();
+ setupOthers();
+ }
- public static Parcel obtain(@NonNull Parcelable target) {
- Parcel parcel = new ParcelMocker(target).getMockedParcel();
- target.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- return parcel;
+ private void setupWrites() {
+ Answer<Void> writeValueAnswer = new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object parameter = invocation.getArguments()[0];
+ objects.add(parameter);
+ return null;
}
-
- public static Parcel obtain(@NonNull Parcelable[] targets) {
- if (targets.length == 0) {
- throw new IllegalArgumentException("The passed argument may not be empty");
+ };
+ Answer<Void> writeArrayAnswer = new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] parameters = (Object[]) invocation.getArguments()[0];
+ objects.add(parameters.length);
+ for (Object o : parameters) {
+ objects.add(o);
+ }
+ return null;
+ }
+ };
+ Answer<Void> writeIntArrayAnswer = new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ int[] parameters = (int[]) invocation.getArguments()[0];
+ if (parameters != null) {
+ objects.add(parameters.length);
+ for (Object o : parameters) {
+ objects.add(o);
}
- Parcel parcel = new ParcelMocker(targets[0]).getMockedParcel();
- parcel.writeParcelableArray(targets, 0);
- parcel.setDataPosition(0);
- return parcel;
+ } else {
+ objects.add(-1);
+ }
+ return null;
}
+ };
+ doAnswer(writeValueAnswer).when(mockedParcel).writeByte(anyByte());
+ doAnswer(writeValueAnswer).when(mockedParcel).writeLong(anyLong());
+ doAnswer(writeValueAnswer).when(mockedParcel).writeString(anyString());
+ doAnswer(writeValueAnswer).when(mockedParcel).writeInt(anyInt());
+ doAnswer(writeIntArrayAnswer).when(mockedParcel).writeIntArray(any(int[].class));
+ doAnswer(writeValueAnswer).when(mockedParcel).writeDouble(anyDouble());
+ doAnswer(writeValueAnswer).when(mockedParcel).writeFloat(anyFloat());
+ doAnswer(writeValueAnswer).when(mockedParcel).writeParcelable(any(Parcelable.class), eq(0));
+ doAnswer(writeArrayAnswer).when(mockedParcel).writeParcelableArray(any(Parcelable[].class), eq(0));
+ }
- private List<Object> objects;
- private Object object;
- private Parcel mockedParcel;
- private int position;
-
- private ParcelMocker(Object o) {
- this.object = o;
- mockedParcel = mock(Parcel.class);
- objects = new ArrayList<>();
- setupMock();
+ private void setupReads() {
+ when(mockedParcel.readInt()).then(new Answer<Integer>() {
+ @Override
+ public Integer answer(InvocationOnMock invocation) throws Throwable {
+ return (Integer) objects.get(position++);
}
-
- private Parcel getMockedParcel() {
- return mockedParcel;
+ });
+ when(mockedParcel.readByte()).thenAnswer(new Answer<Byte>() {
+ @Override
+ public Byte answer(InvocationOnMock invocation) throws Throwable {
+ return (Byte) objects.get(position++);
}
-
- private void setupMock() {
- setupWrites();
- setupReads();
- setupOthers();
+ });
+ when(mockedParcel.readLong()).thenAnswer(new Answer<Long>() {
+ @Override
+ public Long answer(InvocationOnMock invocation) throws Throwable {
+ return (Long) objects.get(position++);
}
-
- private void setupWrites() {
- Answer<Void> writeValueAnswer = new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- Object parameter = invocation.getArguments()[0];
- objects.add(parameter);
- return null;
- }
- };
- Answer<Void> writeArrayAnswer = new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- Object[] parameters = (Object[]) invocation.getArguments()[0];
- objects.add(parameters.length);
- for (Object o : parameters) {
- objects.add(o);
- }
- return null;
- }
- };
- Answer<Void> writeIntArrayAnswer = new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- int[] parameters = (int[]) invocation.getArguments()[0];
- if (parameters != null) {
- objects.add(parameters.length);
- for (Object o : parameters) {
- objects.add(o);
- }
- } else {
- objects.add(-1);
- }
- return null;
- }
- };
- doAnswer(writeValueAnswer).when(mockedParcel).writeByte(anyByte());
- doAnswer(writeValueAnswer).when(mockedParcel).writeLong(anyLong());
- doAnswer(writeValueAnswer).when(mockedParcel).writeString(anyString());
- doAnswer(writeValueAnswer).when(mockedParcel).writeInt(anyInt());
- doAnswer(writeIntArrayAnswer).when(mockedParcel).writeIntArray(any(int[].class));
- doAnswer(writeValueAnswer).when(mockedParcel).writeDouble(anyDouble());
- doAnswer(writeValueAnswer).when(mockedParcel).writeFloat(anyFloat());
- doAnswer(writeValueAnswer).when(mockedParcel).writeParcelable(any(Parcelable.class), eq(0));
- doAnswer(writeArrayAnswer).when(mockedParcel).writeParcelableArray(any(Parcelable[].class), eq(0));
+ });
+ when(mockedParcel.readString()).thenAnswer(new Answer<String>() {
+ @Override
+ public String answer(InvocationOnMock invocation) throws Throwable {
+ return (String) objects.get(position++);
+ }
+ });
+ when(mockedParcel.readDouble()).thenAnswer(new Answer<Double>() {
+ @Override
+ public Double answer(InvocationOnMock invocation) throws Throwable {
+ return (Double) objects.get(position++);
+ }
+ });
+ when(mockedParcel.readFloat()).thenAnswer(new Answer<Float>() {
+ @Override
+ public Float answer(InvocationOnMock invocation) throws Throwable {
+ return (Float) objects.get(position++);
}
+ });
+ when(mockedParcel.readParcelable(Parcelable.class.getClassLoader())).thenAnswer(new Answer<Parcelable>() {
+ @Override
+ public Parcelable answer(InvocationOnMock invocation) throws Throwable {
+ return (Parcelable) objects.get(position++);
+ }
+ });
+ when(mockedParcel.readParcelableArray(Parcelable.class.getClassLoader())).thenAnswer(new Answer<Object[]>() {
+ @Override
+ public Object[] answer(InvocationOnMock invocation) throws Throwable {
+ int size = (Integer) objects.get(position++);
+ Field field = object.getClass().getDeclaredField("CREATOR");
+ field.setAccessible(true);
+ Class<?> creatorClass = field.getType();
+ Object fieldValue = field.get(object);
+ Method myMethod = creatorClass.getDeclaredMethod("newArray", int.class);
+ Object[] array = (Object[]) myMethod.invoke(fieldValue, size);
+ for (int i = 0; i < size; i++) {
+ array[i] = objects.get(position++);
+ }
+ return array;
+ }
+ });
+ when(mockedParcel.createIntArray()).then(new Answer<int[]>() {
+ @Override
+ public int[] answer(InvocationOnMock invocation) throws Throwable {
+ int size = (Integer) objects.get(position++);
+ if (size == -1) {
+ return null;
+ }
- private void setupReads() {
- when(mockedParcel.readInt()).then(new Answer<Integer>() {
- @Override
- public Integer answer(InvocationOnMock invocation) throws Throwable {
- return (Integer) objects.get(position++);
- }
- });
- when(mockedParcel.readByte()).thenAnswer(new Answer<Byte>() {
- @Override
- public Byte answer(InvocationOnMock invocation) throws Throwable {
- return (Byte) objects.get(position++);
- }
- });
- when(mockedParcel.readLong()).thenAnswer(new Answer<Long>() {
- @Override
- public Long answer(InvocationOnMock invocation) throws Throwable {
- return (Long) objects.get(position++);
- }
- });
- when(mockedParcel.readString()).thenAnswer(new Answer<String>() {
- @Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- return (String) objects.get(position++);
- }
- });
- when(mockedParcel.readDouble()).thenAnswer(new Answer<Double>() {
- @Override
- public Double answer(InvocationOnMock invocation) throws Throwable {
- return (Double) objects.get(position++);
- }
- });
- when(mockedParcel.readFloat()).thenAnswer(new Answer<Float>() {
- @Override
- public Float answer(InvocationOnMock invocation) throws Throwable {
- return (Float) objects.get(position++);
- }
- });
- when(mockedParcel.readParcelable(Parcelable.class.getClassLoader())).thenAnswer(new Answer<Parcelable>() {
- @Override
- public Parcelable answer(InvocationOnMock invocation) throws Throwable {
- return (Parcelable) objects.get(position++);
- }
- });
- when(mockedParcel.readParcelableArray(Parcelable.class.getClassLoader())).thenAnswer(new Answer<Object[]>() {
- @Override
- public Object[] answer(InvocationOnMock invocation) throws Throwable {
- int size = (Integer) objects.get(position++);
- Field field = object.getClass().getDeclaredField("CREATOR");
- field.setAccessible(true);
- Class<?> creatorClass = field.getType();
- Object fieldValue = field.get(object);
- Method myMethod = creatorClass.getDeclaredMethod("newArray", int.class);
- Object[] array = (Object[]) myMethod.invoke(fieldValue, size);
- for (int i = 0; i < size; i++) {
- array[i] = objects.get(position++);
- }
- return array;
- }
- });
- when(mockedParcel.createIntArray()).then(new Answer<int[]>() {
- @Override
- public int[] answer(InvocationOnMock invocation) throws Throwable {
- int size = (Integer) objects.get(position++);
- if (size == -1) {
- return null;
- }
-
- int[] array = new int[size];
- for (int i = 0; i < size; i++) {
- array[i] = (Integer) objects.get(position++);
- }
-
- return array;
- }
- });
+ int[] array = new int[size];
+ for (int i = 0; i < size; i++) {
+ array[i] = (Integer) objects.get(position++);
+ }
+
+ return array;
}
+ });
+ }
- private void setupOthers() {
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- position = ((Integer) invocation.getArguments()[0]);
- return null;
- }
- }).when(mockedParcel).setDataPosition(anyInt());
+ private void setupOthers() {
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ position = ((Integer) invocation.getArguments()[0]);
+ return null;
}
+ }).when(mockedParcel).setDataPosition(anyInt());
}
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/platform/android/MapboxGLAndroidSDKTestApp/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..ca6ee9cea8
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+mock-maker-inline \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/update_icons.sh b/platform/android/MapboxGLAndroidSDKTestApp/update_icons.sh
deleted file mode 100755
index ef5213d4f9..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/update_icons.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-if [[ -z `which iconoblast` ]]; then
- echo "Requires https://github.com/mapbox/iconoblast"
- exit 1
-fi
-
-commit=`git rev-parse --short HEAD`
-branch=`git rev-parse --abbrev-ref HEAD`
-repo=`git remote show origin | grep 'Fetch URL' | sed -e 's/.*github\.com:mapbox\///' -e 's/\.git$//' -e 's/^mapbox-//'`
-
-pwd=`pwd`
-cd src/main/res
-for folder in `find . -maxdepth 1 -type d -name drawable-\*`
-do
- cd ${folder}
- cp icon.png icon_burned.png
- iconoblast icon_burned.png $commit $branch $repo
- cd ..
-done
-cd ${pwd}
diff --git a/platform/android/MapboxGLAndroidSDKWearTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKWearTestApp/build.gradle
index 6bd1fac322..1f0e8cb72b 100644
--- a/platform/android/MapboxGLAndroidSDKWearTestApp/build.gradle
+++ b/platform/android/MapboxGLAndroidSDKWearTestApp/build.gradle
@@ -1,37 +1,26 @@
apply plugin: 'com.android.application'
-task accessToken {
- def tokenFile = new File("MapboxGLAndroidSDKWearTestApp/src/main/res/values/developer-config.xml")
- if (!tokenFile.exists()) {
- String tokenFileContents = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
- "<resources>\n" +
- " <string name=\"mapbox_access_token\">" + "$System.env.MAPBOX_ACCESS_TOKEN" + "</string>\n" +
- "</resources>"
-
- if (tokenFileContents == null) {
- throw new InvalidUserDataException("You must set the MAPBOX_ACCESS_TOKEN environment variable.")
- }
- tokenFile.write(tokenFileContents)
- }
-}
-
-gradle.projectsEvaluated {
- preBuild.dependsOn('accessToken')
+ext {
+ wearableVersion = '2.0.0-alpha3'
+ leakCanaryVersion = '1.5'
}
android {
- compileSdkVersion 24
- buildToolsVersion "24.0.2"
+ compileSdkVersion 25
+ buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.mapbox.mapboxsdk.testapp"
minSdkVersion 21
- targetSdkVersion 24
- versionCode 1
- versionName "1.0"
+ targetSdkVersion 25
+ versionCode 11
+ versionName "5.0.0"
}
buildTypes {
+ debug {
+ testCoverageEnabled = true
+ }
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
@@ -44,14 +33,20 @@ dependencies {
transitive = true
}
+ // Wear
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile "com.google.android.support:wearable:${wearableVersion}"
+ provided "com.google.android.wearable:wearable:${wearableVersion}"
+
// Leak Canary
- androidTestCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
- debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2'
- releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
+ debugCompile "com.squareup.leakcanary:leakcanary-android:${leakCanaryVersion}"
+ releaseCompile "com.squareup.leakcanary:leakcanary-android-no-op:${leakCanaryVersion}"
+ testCompile "com.squareup.leakcanary:leakcanary-android-no-op:${leakCanaryVersion}"
- compile fileTree(dir: 'libs', include: ['*.jar'])
- compile 'com.google.android.support:wearable:2.0.0-alpha3'
- provided 'com.google.android.wearable:wearable:2.0.0-alpha3'
+ // Testing dependencies
+ testCompile 'junit:junit:4.12'
+ testCompile 'org.mockito:mockito-core:2.2.27'
}
-apply from: '../checkstyle.gradle' \ No newline at end of file
+apply from: 'gradle-config.gradle'
+apply from: 'gradle-checkstyle.gradle' \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKWearTestApp/gradle-checkstyle.gradle b/platform/android/MapboxGLAndroidSDKWearTestApp/gradle-checkstyle.gradle
new file mode 100644
index 0000000000..cdcc7f1e23
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKWearTestApp/gradle-checkstyle.gradle
@@ -0,0 +1,17 @@
+apply plugin: 'checkstyle'
+
+checkstyle {
+ toolVersion = "7.1.1" // 7.3
+ configFile = "../checkstyle.xml" as File
+}
+
+task checkstyle(type: Checkstyle) {
+ description 'Checks if the code adheres to coding standards'
+ group 'verification'
+ configFile file("../checkstyle.xml")
+ source 'src'
+ include '**/*.java'
+ exclude '**/gen/**'
+ classpath = files()
+ ignoreFailures = false
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKWearTestApp/gradle-config.gradle b/platform/android/MapboxGLAndroidSDKWearTestApp/gradle-config.gradle
new file mode 100644
index 0000000000..fac47cb2a9
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKWearTestApp/gradle-config.gradle
@@ -0,0 +1,22 @@
+//
+// Configuration file for gradle build execution.
+//
+
+task accessToken {
+ def tokenFile = new File("MapboxGLAndroidSDKWearTestApp/src/main/res/values/developer-config.xml")
+ if (!tokenFile.exists()) {
+ String tokenFileContents = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<resources>\n" +
+ " <string name=\"mapbox_access_token\">" + "$System.env.MAPBOX_ACCESS_TOKEN" + "</string>\n" +
+ "</resources>"
+
+ if (tokenFileContents == null) {
+ throw new InvalidUserDataException("You must set the MAPBOX_ACCESS_TOKEN environment variable.")
+ }
+ tokenFile.write(tokenFileContents)
+ }
+}
+
+gradle.projectsEvaluated {
+ preBuild.dependsOn('accessToken')
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/MapboxApplication.java b/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/MapboxApplication.java
index 390c7370cb..cbbdcb8493 100644
--- a/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/MapboxApplication.java
+++ b/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/MapboxApplication.java
@@ -3,7 +3,7 @@ package com.mapbox.weartestapp;
import android.app.Application;
import android.os.StrictMode;
-import com.mapbox.mapboxsdk.MapboxAccountManager;
+import com.mapbox.mapboxsdk.Mapbox;
import com.squareup.leakcanary.LeakCanary;
public class MapboxApplication extends Application {
@@ -11,7 +11,7 @@ public class MapboxApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
- MapboxAccountManager.start(getApplicationContext(), getString(R.string.mapbox_access_token));
+ Mapbox.getInstance(getApplicationContext(), getString(R.string.mapbox_access_token));
LeakCanary.install(this);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
diff --git a/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/activity/FeatureOverviewActivity.java b/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/activity/FeatureOverviewActivity.java
index 7f2caa4d67..2a8bf9396f 100644
--- a/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/activity/FeatureOverviewActivity.java
+++ b/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/activity/FeatureOverviewActivity.java
@@ -15,7 +15,6 @@ import java.util.List;
public class FeatureOverviewActivity extends WearableActivity implements FeatureAdapter.ItemSelectedListener {
- private static final String TAG = "MainActivity";
private WearableRecyclerView wearableRecyclerView;
private List<Feature> exampleItemModels;
@@ -32,7 +31,8 @@ public class FeatureOverviewActivity extends WearableActivity implements Feature
wearableRecyclerView.setOffsettingHelper(offsettingHelper);
exampleItemModels = new ArrayList<>();
- exampleItemModels.add(new Feature(R.string.activity_simple_mapview_title, new Intent(FeatureOverviewActivity.this, SimpleMapViewActivity.class)));
+ exampleItemModels.add(new Feature(R.string.activity_simple_mapview_title, new Intent(FeatureOverviewActivity.this,
+ SimpleMapViewActivity.class)));
FeatureAdapter exampleAdapter = new FeatureAdapter(FeatureOverviewActivity.this, exampleItemModels);
wearableRecyclerView.setAdapter(exampleAdapter);
diff --git a/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/activity/SimpleMapViewActivity.java b/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/activity/SimpleMapViewActivity.java
index d6f3ccd410..b24b626fe6 100644
--- a/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/activity/SimpleMapViewActivity.java
+++ b/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/java/com/mapbox/weartestapp/activity/SimpleMapViewActivity.java
@@ -29,18 +29,30 @@ public class SimpleMapViewActivity extends WearableActivity {
}
@Override
- public void onResume() {
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
- public void onPause() {
+ protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
diff --git a/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/res/layout/activity_simple_mapview.xml b/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/res/layout/activity_simple_mapview.xml
index 2c1e5fe2eb..948f92e30b 100644
--- a/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/res/layout/activity_simple_mapview.xml
+++ b/platform/android/MapboxGLAndroidSDKWearTestApp/src/main/res/layout/activity_simple_mapview.xml
@@ -13,10 +13,10 @@
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- mapbox:center_latitude="40.73581"
- mapbox:center_longitude="-73.99155"
- mapbox:style_url="mapbox://styles/mapbox/streets-v9"
- mapbox:zoom="11"
- mapbox:zoom_controls_enabled="false"/>
+ mapbox:mapbox_cameraTargetLat="40.73581"
+ mapbox:mapbox_cameraTargetLng="-73.99155"
+ mapbox:mapbox_styleUrl="mapbox://styles/mapbox/streets-v9"
+ mapbox:mapbox_cameraZoom="11"
+ mapbox:mapbox_uiZoomControls="false"/>
</FrameLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKWearTestApp/src/test/java/com/mapbox/weartestapp/utils/OffsettingHelperTest.java b/platform/android/MapboxGLAndroidSDKWearTestApp/src/test/java/com/mapbox/weartestapp/utils/OffsettingHelperTest.java
new file mode 100644
index 0000000000..aab7714947
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKWearTestApp/src/test/java/com/mapbox/weartestapp/utils/OffsettingHelperTest.java
@@ -0,0 +1,28 @@
+package com.mapbox.weartestapp.utils;
+
+import android.view.View;
+
+import org.junit.Test;
+import org.mockito.InjectMocks;
+
+import static junit.framework.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class OffsettingHelperTest {
+
+ private static final double DELTA = 1e-15;
+
+ @InjectMocks
+ View view = mock(View.class);
+
+ @Test
+ public void testAnchorOffset() {
+ float[] offset = new float[2];
+ int viewHeight = 50;
+ when(view.getHeight()).thenReturn(viewHeight);
+ OffsettingHelper offsettingHelper = new OffsettingHelper();
+ offsettingHelper.adjustAnchorOffsetXY(view, offset);
+ assertEquals("Offset of " + viewHeight + " should be divided by 2: ", viewHeight / 2, offset[0], DELTA);
+ }
+}
diff --git a/platform/android/bitrise.yml b/platform/android/bitrise.yml
index c168a9a6d6..fcc28e05f9 100644
--- a/platform/android/bitrise.yml
+++ b/platform/android/bitrise.yml
@@ -6,6 +6,8 @@ trigger_map:
workflow: devicefarmUpload
- pattern: scheduled
workflow: scheduled
+- pattern: nightly-release
+ workflow: nightly-release
- pattern: "*"
workflow: primary
workflows:
@@ -35,6 +37,14 @@ workflows:
curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
sudo apt-get install -y pkg-config nodejs cmake
- script:
+ title: Run Checkstyle
+ run_if: '{{enveq "SKIPCI" "false"}}'
+ inputs:
+ - content: |-
+ #!/bin/bash
+ # Run checkstyle gradle task on all modules
+ cd platform/android && ./gradlew checkstyle
+ - script:
title: Configure Google Cloud SDK
run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
@@ -50,10 +60,10 @@ workflows:
export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)"
echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | sudo tee /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
- sudo apt-get update && sudo apt-get install google-cloud-sdk
+ sudo apt-get update && sudo apt-get install -y google-cloud-sdk
# Get authentication secret
- echo "Downloading Google Cloud authnetication:"
+ echo "Downloading Google Cloud authentication:"
wget -O secret.json "$BITRISEIO_GCLOUD_SERVICE_ACCOUNT_JSON_URL"
- script:
title: Build libmapbox-gl.so for armeabi-v7a
@@ -65,13 +75,29 @@ workflows:
export BUILDTYPE=Debug
make android-lib-arm-v7
- script:
- title: Run local JVM Unit tests
+ title: Compile Core tests
+ run_if: '{{enveq "SKIPCI" "false"}}'
+ inputs:
+ - content: |-
+ #!/bin/bash
+ echo "Compiling core tests:"
+ BUILDTYPE=Debug make android-test-lib-arm-v7
+ - script:
+ title: Run local JVM Unit tests on phone module
+ run_if: '{{enveq "SKIPCI" "false"}}'
+ inputs:
+ - content: |-
+ #!/bin/bash
+ echo "Running unit tests from MapboxGLAndroidSDKTestApp/src/test:"
+ make run-android-unit-test
+ - script:
+ title: Run local JVM Unit tests on wear module
run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
- echo "Running unit tests from testapp/src/test:"
- make android-test
+ echo "Running unit tests from MapboxGLAndroidSDKWearTestApp/src/test:"
+ make run-android-wear-unit-test
- script:
title: Generate Espresso sanity tests
run_if: '{{enveq "SKIPCI" "false"}}'
@@ -79,7 +105,7 @@ workflows:
- content: |-
#!/bin/bash
echo "Generate these test locally by executing:"
- make android-generate-test
+ make test-code-android
- script:
title: Run Firebase instrumentation tests
run_if: '{{enveq "SKIPCI" "false"}}'
@@ -90,13 +116,12 @@ workflows:
wget -O platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml "$BITRISEIO_TEST_ACCESS_TOKEN_UI_TEST_URL"
echo "Build seperate test apk:"
- make android-test-apk
+ make android-ui-test
echo "Run tests on firebase:"
gcloud auth activate-service-account --key-file secret.json --project android-gl-native
gcloud beta test android devices list
- gcloud beta test android run --type instrumentation --app platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug.apk --test platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug-androidTest-unaligned.apk --device-ids shamu --os-version-ids 22 --locales en --orientations portrait --timeout 15m --test-targets "class com.mapbox.mapboxsdk.testapp.camera.RotateActivityTest"
- echo "The details are made available as a zipped build artefact on top of this page."
+ gcloud beta test android run --type instrumentation --app platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug.apk --test platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug-androidTest.apk --device-ids shamu --os-version-ids 22 --locales en --orientations portrait --timeout 15m --test-targets "class com.mapbox.mapboxsdk.testapp.maps.widgets.AttributionTest"
- script:
title: Download Firebase results
run_if: '{{enveq "SKIPCI" "false"}}'
@@ -104,10 +129,12 @@ workflows:
inputs:
- content: |-
#!/bin/bash
+ mkdir -p platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk
+
echo "The details from Firebase will be downloaded, zipped and attached as a build artefact."
testUri=$(gsutil ls "gs://test-lab-wrrntqk05p31w-h3y1qk44vuunw/" | tail -n1)
echo "Downloading from : "$testUri
- cd platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk && gsutil -m cp -R -Z $testUri .
+ gsutil -m cp -R -Z $testUri platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk
echo "Try running ndk-stack on downloaded logcat to symbolicate the stacktraces:"
find platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk -type f -name "logcat" -print0 | xargs -0 -Imylogcat mv -i mylogcat ./
@@ -188,8 +215,8 @@ workflows:
- channel: "#gl-bots"
- from_username: 'Bitrise Android'
- from_username_on_error: 'Bitrise Android'
- - message: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}> Publish to maven SUCCESS.'
- - message_on_error: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}> Publish to maven FAILED.'
+ - message: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}> Publish of nightly Android SDK SNAPSHOT to maven succeeded.'
+ - message_on_error: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}> Publish of nightly Android SDK SNAPSHOT to maven failed. @android_team.'
- icon_url: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-icon-128.png
- icon_url_on_error: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-error-icon-128.png
devicefarmUpload:
@@ -223,7 +250,7 @@ workflows:
- content: |-
#!/bin/bash
echo "Generate these test locally by executing:"
- make android-generate-test
+ make test-code-android
- script:
title: Run AWS Device Farm instrumentation tests
inputs:
@@ -242,3 +269,35 @@ workflows:
- message_on_error: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}> for devicefarmUpload failed'
- icon_url: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-icon-128.png
- icon_url_on_error: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-error-icon-128.png
+ nightly-release:
+ steps:
+ - script:
+ title: Configure GL-native build environement
+ inputs:
+ - content: |-
+ #!/bin/bash
+ set -eu -o pipefail
+ curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
+ sudo apt-get install -y pkg-config nodejs cmake
+ - script:
+ title: Configure AWS-CLI
+ inputs:
+ - content: |-
+ #!/bin/bash
+ apt-get install -y python-pip python-dev build-essential
+ pip install awscli
+ - script:
+ title: Build release
+ inputs:
+ - content: |-
+ #!/bin/bash
+ echo "Compile libmapbox-gl.so for all supportd abi's:"
+ export BUILDTYPE=Release
+ make apackage
+ - script:
+ title: Log metrics
+ inputs:
+ - content: |-
+ #!/bin/bash
+ echo "Log binary size metrics to AWS CloudWatch:"
+ CLOUDWATCH=true platform/android/scripts/metrics.sh
diff --git a/platform/android/build.gradle b/platform/android/build.gradle
index aed761c837..9ba9210af4 100644
--- a/platform/android/build.gradle
+++ b/platform/android/build.gradle
@@ -4,8 +4,7 @@ buildscript {
maven { url 'https://jitpack.io' }
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.1.3'
- classpath 'com.github.JakeWharton:sdk-manager-plugin:220bf7a88a7072df3ed16dc8466fb144f2817070'
+ classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.amazonaws:aws-devicefarm-gradle-plugin:1.2'
classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.2.1'
}
@@ -18,8 +17,6 @@ allprojects {
}
}
-apply from: 'checkstyle.gradle'
-
task wrapper(type: Wrapper) {
- gradleVersion = '2.14.1'
+ gradleVersion = '3.2.1'
}
diff --git a/platform/android/checkstyle.gradle b/platform/android/checkstyle.gradle
deleted file mode 100644
index 69f7f41ff4..0000000000
--- a/platform/android/checkstyle.gradle
+++ /dev/null
@@ -1,16 +0,0 @@
-apply plugin: 'checkstyle'
-
-checkstyle.toolVersion = '7.1'
-
-task checkstyle(type: Checkstyle) {
- description 'Checks if the code adheres to coding standards'
- group 'verification'
-
- configFile = new File(rootDir, "checkstyle.xml")
- source 'src'
- include '**/*.java'
- exclude '**/gen/**'
-
- classpath = files()
- ignoreFailures = false
-}
diff --git a/platform/android/checkstyle.xml b/platform/android/checkstyle.xml
index 3b4fba7b2e..6a429858a6 100644
--- a/platform/android/checkstyle.xml
+++ b/platform/android/checkstyle.xml
@@ -6,8 +6,8 @@
<module name = "Checker">
<property name="charset" value="UTF-8"/>
- <!-- <property name="severity" value="error"/> -->
- <property name="severity" value="warning"/>
+ <property name="severity" value="error"/>
+ <!-- <property name="severity" value="warning"/> -->
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Checks for whitespace -->
@@ -72,7 +72,7 @@
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
- <module name="MissingSwitchDefault"/>
+ <!--<module name="MissingSwitchDefault"/>-->
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
@@ -92,32 +92,32 @@
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
- <module name="TypeName">
+ <!-- <module name="TypeName">
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
- </module>
- <module name="MemberName">
+ </module> -->
+ <!--<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
- </module>
- <module name="ParameterName">
+ </module>-->
+ <!-- <module name="ParameterName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
- </module>
+ </module> -->
<module name="CatchParameterName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
- <module name="LocalVariableName">
+ <!-- <module name="LocalVariableName">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<property name="allowOneCharVarInForLoop" value="true"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
- </module>
+ </module> -->
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
@@ -133,7 +133,7 @@
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
- <module name="NoFinalizer"/>
+ <!-- <module name="NoFinalizer"/> -->
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
@@ -153,12 +153,12 @@
<property name="arrayInitIndent" value="2"/>
<!-- <property name="forceStrictCondition" value="true"/> -->
</module>
- <module name="AbbreviationAsWordInName">
+ <!-- <module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
- </module>
- <module name="OverloadMethodsDeclarationOrder"/>
- <module name="VariableDeclarationUsageDistance"/>
+ </module> -->
+ <!--<module name="OverloadMethodsDeclarationOrder"/>-->
+ <!--<module name="VariableDeclarationUsageDistance"/>-->
<module name="AvoidStarImport"/>
<module name="IllegalImport"/> <!-- defaults to sun.* packages -->
<module name="RedundantImport"/>
diff --git a/platform/android/config.cmake b/platform/android/config.cmake
index 05037589fb..635c27a44f 100644
--- a/platform/android/config.cmake
+++ b/platform/android/config.cmake
@@ -1,14 +1,52 @@
add_definitions(-DMBGL_USE_GLES2=1)
+include(cmake/test-files.cmake)
+
#Include to use build specific variables
include(${CMAKE_CURRENT_BINARY_DIR}/toolchain.cmake)
+# Build thin archives.
+set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> cruT <TARGET> <LINK_FLAGS> <OBJECTS>")
+set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> cruT <TARGET> <LINK_FLAGS> <OBJECTS>")
+set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> ruT <TARGET> <LINK_FLAGS> <OBJECTS>")
+set(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> ruT <TARGET> <LINK_FLAGS> <OBJECTS>")
+
+if ((ANDROID_ABI STREQUAL "armeabi") OR (ANDROID_ABI STREQUAL "armeabi-v7a") OR (ANDROID_ABI STREQUAL "arm64-v8a") OR
+ (ANDROID_ABI STREQUAL "x86") OR (ANDROID_ABI STREQUAL "x86_64"))
+ # Use Identical Code Folding on platforms that support the gold linker.
+ set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=gold -Wl,--icf=safe ${CMAKE_EXE_LINKER_FLAGS}")
+ set(CMAKE_SHARED_LINKER_FLAGS "-fuse-ld=gold -Wl,--icf=safe ${CMAKE_SHARED_LINKER_FLAGS}")
+endif()
+
mason_use(jni.hpp VERSION 2.0.0 HEADER_ONLY)
mason_use(libjpeg-turbo VERSION 1.5.0)
mason_use(libpng VERSION 1.6.25)
mason_use(libzip VERSION 1.1.3)
mason_use(nunicode VERSION 1.7.1)
mason_use(sqlite VERSION 3.14.2)
+mason_use(gtest VERSION 1.7.0)
+mason_use(icu VERSION 58.1)
+
+set(ANDROID_SDK_PROJECT_DIR ${CMAKE_SOURCE_DIR}/platform/android/MapboxGLAndroidSDK)
+set(ANDROID_JNI_TARGET_DIR ${ANDROID_SDK_PROJECT_DIR}/src/main/jniLibs/${ANDROID_JNIDIR})
+set(ANDROID_ASSETS_TARGET_DIR ${ANDROID_SDK_PROJECT_DIR}/src/main/assets)
+set(ANDROID_TEST_APP_JNI_TARGET_DIR ${CMAKE_SOURCE_DIR}/platform/android/MapboxGLAndroidSDKTestApp/src/main/jniLibs/${ANDROID_JNIDIR})
+
+macro(mbgl_android_copy_asset source target)
+ add_custom_command(
+ OUTPUT ${ANDROID_ASSETS_TARGET_DIR}/${target}
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/${source} ${ANDROID_ASSETS_TARGET_DIR}/${target}
+ DEPENDS ${CMAKE_SOURCE_DIR}/${source}
+ )
+endmacro()
+
+mbgl_android_copy_asset(common/ca-bundle.crt ca-bundle.crt)
+
+add_custom_target(mbgl-copy-android-assets
+ DEPENDS ${ANDROID_ASSETS_TARGET_DIR}/ca-bundle.crt
+)
+
+## mbgl core ##
macro(mbgl_platform_core)
@@ -38,23 +76,85 @@ macro(mbgl_platform_core)
PRIVATE platform/default/sqlite3.hpp
# Misc
- PRIVATE platform/android/src/log_android.cpp
+ PRIVATE platform/android/src/logging_android.cpp
PRIVATE platform/default/string_stdlib.cpp
+ PRIVATE platform/default/bidi.cpp
# Image handling
PRIVATE platform/default/image.cpp
PRIVATE platform/default/png_reader.cpp
PRIVATE platform/default/jpeg_reader.cpp
- # Headless view
- # TODO
-
# Thread pool
- PRIVATE platform/default/thread_pool.cpp
+ PRIVATE platform/default/mbgl/util/default_thread_pool.cpp
+ PRIVATE platform/default/mbgl/util/default_thread_pool.hpp
+
+ # Conversion C++ -> Java
+ platform/android/src/conversion/constant.hpp
+ platform/android/src/conversion/conversion.hpp
+ platform/android/src/style/conversion/function.hpp
+ platform/android/src/style/conversion/property_value.hpp
+ platform/android/src/style/conversion/types.hpp
+ platform/android/src/style/conversion/types_string_values.hpp
+
+ # Style conversion Java -> C++
+ platform/android/src/style/android_conversion.hpp
+ platform/android/src/style/conversion/geojson.hpp
+ platform/android/src/style/value.cpp
+ platform/android/src/style/value.hpp
+ platform/android/src/style/conversion/url_or_tileset.hpp
+
+ # Style
+ platform/android/src/style/layers/background_layer.cpp
+ platform/android/src/style/layers/background_layer.hpp
+ platform/android/src/style/layers/circle_layer.cpp
+ platform/android/src/style/layers/circle_layer.hpp
+ platform/android/src/style/layers/custom_layer.cpp
+ platform/android/src/style/layers/custom_layer.hpp
+ platform/android/src/style/layers/fill_layer.cpp
+ platform/android/src/style/layers/fill_layer.hpp
+ platform/android/src/style/layers/layer.cpp
+ platform/android/src/style/layers/layer.hpp
+ platform/android/src/style/layers/layers.cpp
+ platform/android/src/style/layers/layers.hpp
+ platform/android/src/style/layers/line_layer.cpp
+ platform/android/src/style/layers/line_layer.hpp
+ platform/android/src/style/layers/raster_layer.cpp
+ platform/android/src/style/layers/raster_layer.hpp
+ platform/android/src/style/layers/symbol_layer.cpp
+ platform/android/src/style/layers/symbol_layer.hpp
+ platform/android/src/style/sources/geojson_source.cpp
+ platform/android/src/style/sources/geojson_source.hpp
+ platform/android/src/style/sources/source.cpp
+ platform/android/src/style/sources/source.hpp
+ platform/android/src/style/sources/sources.cpp
+ platform/android/src/style/sources/sources.hpp
+ platform/android/src/style/sources/raster_source.cpp
+ platform/android/src/style/sources/raster_source.hpp
+ platform/android/src/style/sources/vector_source.cpp
+ platform/android/src/style/sources/vector_source.hpp
+
+ # Connectivity
+ platform/android/src/connectivity_listener.cpp
+ platform/android/src/connectivity_listener.hpp
+
+ # Native map
+ platform/android/src/native_map_view.cpp
+ platform/android/src/native_map_view.hpp
+
+ # Main jni bindings
+ platform/android/src/attach_env.cpp
+ platform/android/src/attach_env.hpp
+ platform/android/src/java_types.cpp
+ platform/android/src/java_types.hpp
+
+ # Main entry point
+ platform/android/src/jni.hpp
+ platform/android/src/jni.cpp
)
target_include_directories(mbgl-core
- PRIVATE platform/default
+ PUBLIC platform/default
)
target_add_mason_package(mbgl-core PUBLIC sqlite)
@@ -64,9 +164,13 @@ macro(mbgl_platform_core)
target_add_mason_package(mbgl-core PUBLIC libzip)
target_add_mason_package(mbgl-core PUBLIC geojson)
target_add_mason_package(mbgl-core PUBLIC jni.hpp)
+ target_add_mason_package(mbgl-core PUBLIC rapidjson)
+ target_add_mason_package(mbgl-core PUBLIC icu)
target_compile_options(mbgl-core
PRIVATE -fvisibility=hidden
+ PRIVATE -ffunction-sections
+ PRIVATE -fdata-sections
PRIVATE -Os
)
@@ -78,114 +182,118 @@ macro(mbgl_platform_core)
PUBLIC -lstdc++
PUBLIC -latomic
PUBLIC -lz
+ PUBLIC -Wl,--gc-sections
)
endmacro()
+## Main library ##
+
add_library(mapbox-gl SHARED
- # Conversion C++ -> Java
- platform/android/src/conversion/constant.hpp
- platform/android/src/conversion/conversion.hpp
- platform/android/src/style/conversion/function.hpp
- platform/android/src/style/conversion/property_value.hpp
- platform/android/src/style/conversion/types.hpp
- platform/android/src/style/conversion/types_string_values.hpp
-
- # Style conversion Java -> C++
- platform/android/src/style/android_conversion.hpp
- platform/android/src/style/conversion/geojson.hpp
- platform/android/src/style/value.cpp
- platform/android/src/style/value.hpp
- platform/android/src/style/conversion/url_or_tileset.hpp
-
- # Style
- platform/android/src/style/layers/background_layer.cpp
- platform/android/src/style/layers/background_layer.hpp
- platform/android/src/style/layers/circle_layer.cpp
- platform/android/src/style/layers/circle_layer.hpp
- platform/android/src/style/layers/custom_layer.cpp
- platform/android/src/style/layers/custom_layer.hpp
- platform/android/src/style/layers/fill_layer.cpp
- platform/android/src/style/layers/fill_layer.hpp
- platform/android/src/style/layers/layer.cpp
- platform/android/src/style/layers/layer.hpp
- platform/android/src/style/layers/layers.cpp
- platform/android/src/style/layers/layers.hpp
- platform/android/src/style/layers/line_layer.cpp
- platform/android/src/style/layers/line_layer.hpp
- platform/android/src/style/layers/raster_layer.cpp
- platform/android/src/style/layers/raster_layer.hpp
- platform/android/src/style/layers/symbol_layer.cpp
- platform/android/src/style/layers/symbol_layer.hpp
- platform/android/src/style/sources/geojson_source.cpp
- platform/android/src/style/sources/geojson_source.hpp
- platform/android/src/style/sources/source.cpp
- platform/android/src/style/sources/source.hpp
- platform/android/src/style/sources/sources.cpp
- platform/android/src/style/sources/sources.hpp
- platform/android/src/style/sources/raster_source.cpp
- platform/android/src/style/sources/raster_source.hpp
- platform/android/src/style/sources/vector_source.cpp
- platform/android/src/style/sources/vector_source.hpp
-
- # Native map
- platform/android/src/native_map_view.cpp
- platform/android/src/native_map_view.hpp
-
- # Connectivity
- platform/android/src/connectivity_listener.cpp
- platform/android/src/connectivity_listener.hpp
-
- # Main jni bindings
- platform/android/src/jni.cpp
- platform/android/src/jni.hpp
- platform/android/src/attach_env.cpp
- platform/android/src/attach_env.hpp
- platform/android/src/java_types.cpp
- platform/android/src/java_types.hpp
+ platform/android/src/main.cpp
)
-target_add_mason_package(mapbox-gl PUBLIC rapidjson)
+add_dependencies(mapbox-gl
+ mbgl-copy-android-assets
+)
target_compile_options(mapbox-gl
PRIVATE -fvisibility=hidden
+ PRIVATE -ffunction-sections
+ PRIVATE -fdata-sections
PRIVATE -Os
)
target_link_libraries(mapbox-gl
PUBLIC mbgl-core
+ PUBLIC -Wl,--gc-sections
)
-add_library(example-custom-layer SHARED
- platform/android/src/example_custom_layer.cpp
+# Create a stripped version of the library and copy it to the JNIDIR.
+add_custom_command(TARGET mapbox-gl POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${ANDROID_JNI_TARGET_DIR}
+ COMMAND ${STRIP_COMMAND} $<TARGET_FILE:mapbox-gl> -o ${ANDROID_JNI_TARGET_DIR}/$<TARGET_FILE_NAME:mapbox-gl>)
+
+## Test library ##
+
+add_library(mbgl-test SHARED
+ # Actual tests
+ ${MBGL_TEST_FILES}
+
+ # Main test entry point
+ platform/android/src/test/main.jni.cpp
+
)
-target_compile_options(example-custom-layer
+add_dependencies(mbgl-test
+ mapbox-gl
+)
+
+target_sources(mbgl-test
+ # Headless view
+ PRIVATE platform/default/mbgl/gl/headless_backend.cpp
+ PRIVATE platform/default/mbgl/gl/headless_backend.hpp
+ PRIVATE platform/default/mbgl/gl/offscreen_view.cpp
+ PRIVATE platform/default/mbgl/gl/offscreen_view.hpp
+
+ PRIVATE platform/linux/src/headless_backend_egl.cpp
+ PRIVATE platform/linux/src/headless_display_egl.cpp
+)
+
+target_compile_options(mbgl-test
PRIVATE -fvisibility=hidden
PRIVATE -Os
)
-target_link_libraries(example-custom-layer
+target_compile_definitions(mbgl-test
+ PRIVATE MBGL_ASSET_ZIP=1
+)
+
+target_include_directories(mbgl-test
+ PRIVATE include
+ PRIVATE src # TODO: eliminate
+ PRIVATE test/include
+ PRIVATE test/src
+ PRIVATE platform/default
+ PRIVATE ${MBGL_GENERATED}/include
+)
+
+target_link_libraries(mbgl-test
PRIVATE mbgl-core
)
-set(ANDROID_SDK_PROJECT_DIR ${CMAKE_SOURCE_DIR}/platform/android/MapboxGLAndroidSDK)
-set(ANDROID_JNI_TARGET_DIR ${ANDROID_SDK_PROJECT_DIR}/src/main/jniLibs/${ANDROID_JNIDIR}/)
-set(ANDROID_ASSETS_TARGET_DIR ${ANDROID_SDK_PROJECT_DIR}/src/main/assets/)
-set(ANDROID_TEST_APP_JNI_TARGET_DIR ${CMAKE_SOURCE_DIR}/platform/android/MapboxGLAndroidSDKTestApp/src/main/jniLibs/${ANDROID_JNIDIR}/)
-
-add_custom_target(copy-files
- DEPENDS mapbox-gl
- DEPENDS example-custom-layer
- COMMAND ${CMAKE_COMMAND} -E make_directory ${ANDROID_JNI_TARGET_DIR}
- COMMAND ${STRIP_COMMAND} $<TARGET_FILE:mapbox-gl> -o ${ANDROID_JNI_TARGET_DIR}$<TARGET_FILE_NAME:mapbox-gl>
- COMMAND ${CMAKE_COMMAND} -E make_directory ${ANDROID_ASSETS_TARGET_DIR}
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/common/ca-bundle.crt ${ANDROID_ASSETS_TARGET_DIR}
- COMMAND ${CMAKE_COMMAND} -E make_directory ${ANDROID_TEST_APP_JNI_TARGET_DIR}
- COMMAND ${STRIP_COMMAND} $<TARGET_FILE:example-custom-layer> -o ${ANDROID_TEST_APP_JNI_TARGET_DIR}$<TARGET_FILE_NAME:example-custom-layer>
+target_add_mason_package(mbgl-test PRIVATE geometry)
+target_add_mason_package(mbgl-test PRIVATE variant)
+target_add_mason_package(mbgl-test PRIVATE unique_resource)
+target_add_mason_package(mbgl-test PRIVATE rapidjson)
+target_add_mason_package(mbgl-test PRIVATE gtest)
+target_add_mason_package(mbgl-test PRIVATE pixelmatch)
+target_add_mason_package(mbgl-test PRIVATE boost)
+target_add_mason_package(mbgl-test PRIVATE geojson)
+target_add_mason_package(mbgl-test PRIVATE geojsonvt)
+
+add_custom_command(TARGET mbgl-test POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/stripped
+ COMMAND ${STRIP_COMMAND} $<TARGET_FILE:mapbox-gl> -o ${CMAKE_CURRENT_BINARY_DIR}/stripped/$<TARGET_FILE_NAME:mapbox-gl>
+ COMMAND ${STRIP_COMMAND} $<TARGET_FILE:mbgl-test> -o ${CMAKE_CURRENT_BINARY_DIR}/stripped/$<TARGET_FILE_NAME:mbgl-test>)
+
+## Custom layer example ##
+
+add_library(example-custom-layer SHARED
+ platform/android/src/example_custom_layer.cpp
)
-add_custom_target(_all ALL
- DEPENDS mapbox-gl
- DEPENDS example-custom-layer
- DEPENDS copy-files
+target_compile_options(example-custom-layer
+ PRIVATE -fvisibility=hidden
+ PRIVATE -ffunction-sections
+ PRIVATE -fdata-sections
+ PRIVATE -Os
+)
+
+target_link_libraries(example-custom-layer
+ PRIVATE mapbox-gl
+ PUBLIC -Wl,--gc-sections
)
+
+add_custom_command(TARGET example-custom-layer POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${ANDROID_TEST_APP_JNI_TARGET_DIR}
+ COMMAND ${STRIP_COMMAND} $<TARGET_FILE:example-custom-layer> -o ${ANDROID_TEST_APP_JNI_TARGET_DIR}/$<TARGET_FILE_NAME:example-custom-layer>)
diff --git a/platform/android/gradle/wrapper/gradle-wrapper.jar b/platform/android/gradle/wrapper/gradle-wrapper.jar
index 3baa851b28..51288f9c2f 100644
--- a/platform/android/gradle/wrapper/gradle-wrapper.jar
+++ b/platform/android/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/platform/android/gradle/wrapper/gradle-wrapper.properties b/platform/android/gradle/wrapper/gradle-wrapper.properties
index 1a4f00cd31..20b2b0894c 100644
--- a/platform/android/gradle/wrapper/gradle-wrapper.properties
+++ b/platform/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,7 +1,6 @@
-#Wed Aug 17 09:21:12 EDT 2016
+#Mon Dec 12 10:58:15 CET 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
-distributionSha256Sum=88a910cdf2e03ebbb5fe90f7ecf534fc9ac22e12112dc9a2fee810c598a76091
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-bin.zip
diff --git a/platform/android/gradlew b/platform/android/gradlew
index 27309d9231..4453ccea33 100755
--- a/platform/android/gradlew
+++ b/platform/android/gradlew
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
##############################################################################
##
@@ -154,11 +154,19 @@ if $cygwin ; then
esac
fi
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
- JVM_OPTS=("$@")
+# Escape application args
+save ( ) {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
}
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+APP_ARGS=$(save "$@")
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/platform/android/gradlew.bat b/platform/android/gradlew.bat
index f6d5974e72..e95643d6a2 100644
--- a/platform/android/gradlew.bat
+++ b/platform/android/gradlew.bat
@@ -49,7 +49,6 @@ goto fail
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
-if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
-goto execute
-
-:4NT_args
-@rem Get arguments from the 4NT Shell from JP Software
-set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
diff --git a/platform/android/scripts/generate-style-code.js b/platform/android/scripts/generate-style-code.js
index 1216bd4cbe..bcfd6bc0df 100644
--- a/platform/android/scripts/generate-style-code.js
+++ b/platform/android/scripts/generate-style-code.js
@@ -5,6 +5,8 @@ const ejs = require('ejs');
const spec = require('mapbox-gl-style-spec').latest;
const _ = require('lodash');
+require('../../../scripts/style-code');
+
// Specification parsing //
//Collect layer types from spec
@@ -38,29 +40,6 @@ const paintProperties = _(layers).map('paintProperties').flatten().value();
const allProperties = _(layoutProperties).union(paintProperties).value();
const enumProperties = _(allProperties).filter({'type': 'enum'}).value();
-// Global functions //
-
-global.iff = function (condition, val) {
- return condition() ? val : "";
-}
-
-
-global.camelize = function (str) {
- return str.replace(/(?:^|-)(.)/g, function (_, x) {
- return x.toUpperCase();
- });
-}
-
-global.camelizeWithLeadingLowercase = function (str) {
- return str.replace(/-(.)/g, function (_, x) {
- return x.toUpperCase();
- });
-}
-
-global.snakeCaseUpper = function snakeCaseUpper(str) {
- return str.replace(/-/g, "_").toUpperCase();
-}
-
global.propertyType = function propertyType(property) {
switch (property.type) {
case 'boolean':
@@ -235,7 +214,6 @@ global.propertyValueDoc = function (property, value) {
// Template processing //
-
// Java + JNI Layers (Peer model)
const layerHpp = ejs.compile(fs.readFileSync('platform/android/src/style/layers/layer.hpp.ejs', 'utf8'), {strict: true});
const layerCpp = ejs.compile(fs.readFileSync('platform/android/src/style/layers/layer.cpp.ejs', 'utf8'), {strict: true});
@@ -243,23 +221,23 @@ const layerJava = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidS
const layerJavaUnitTests = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs', 'utf8'), {strict: true});
for (const layer of layers) {
- fs.writeFileSync(`platform/android/src/style/layers/${layer.type}_layer.hpp`, layerHpp(layer));
- fs.writeFileSync(`platform/android/src/style/layers/${layer.type}_layer.cpp`, layerCpp(layer));
- fs.writeFileSync(`platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/${camelize(layer.type)}Layer.java`, layerJava(layer));
- fs.writeFileSync(`platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/${camelize(layer.type)}LayerTest.java`, layerJavaUnitTests(layer));
+ writeIfModified(`platform/android/src/style/layers/${layer.type.replace('-', '_')}_layer.hpp`, layerHpp(layer));
+ writeIfModified(`platform/android/src/style/layers/${layer.type.replace('-', '_')}_layer.cpp`, layerCpp(layer));
+ writeIfModified(`platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/${camelize(layer.type)}Layer.java`, layerJava(layer));
+ writeIfModified(`platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/${camelize(layer.type)}LayerTest.java`, layerJavaUnitTests(layer));
}
// Java PropertyFactory
const propertiesTemplate = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs', 'utf8'), {strict: true});
-fs.writeFileSync(
+writeIfModified(
`platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java`,
propertiesTemplate({layoutProperties: layoutProperties, paintProperties: paintProperties})
);
// Java Property
const enumPropertyJavaTemplate = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property.java.ejs', 'utf8'), {strict: true});
-fs.writeFileSync(
+writeIfModified(
`platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java`,
enumPropertyJavaTemplate({properties: enumProperties})
);
@@ -269,14 +247,14 @@ const enumPropertiesDeDup = _(enumProperties).uniqBy(global.propertyNativeType).
// JNI Enum property conversion templates
const enumPropertyHppTypeStringValueTemplate = ejs.compile(fs.readFileSync('platform/android/src/style/conversion/types_string_values.hpp.ejs', 'utf8'), {strict: true});
-fs.writeFileSync(
+writeIfModified(
`platform/android/src/style/conversion/types_string_values.hpp`,
enumPropertyHppTypeStringValueTemplate({properties: enumPropertiesDeDup})
);
// JNI property value types conversion templates
const enumPropertyHppTypeTemplate = ejs.compile(fs.readFileSync('platform/android/src/style/conversion/types.hpp.ejs', 'utf8'), {strict: true});
-fs.writeFileSync(
+writeIfModified(
`platform/android/src/style/conversion/types.hpp`,
enumPropertyHppTypeTemplate({properties: enumPropertiesDeDup})
);
diff --git a/platform/android/scripts/generate-test-code.js b/platform/android/scripts/generate-test-code.js
index 17f0079906..2fd98f701f 100644
--- a/platform/android/scripts/generate-test-code.js
+++ b/platform/android/scripts/generate-test-code.js
@@ -14,7 +14,7 @@ global.camelize = function (str) {
}
-const excludeActivities = ["UpdateMetadataActivity","CarDrivingActivity","MyLocationTrackingModeActivity","MyLocationToggleActivity","MyLocationTintActivity","MyLocationDrawableActivity","DoubleMapActivity", "LocationPickerActivity","GeoJsonClusteringActivity","RuntimeStyleTestActivity", "AnimatedMarkerActivity", "ViewPagerActivity","MapFragmentActivity","SupportMapFragmentActivity","SnapshotActivity","NavigationDrawerActivity", "QueryRenderedFeaturesBoxHighlightActivity", "MultiMapActivity", "MapInDialogActivity"];
+const excludeActivities = ["RealTimeGeoJsonActivity","UpdateMetadataActivity","CarDrivingActivity","MyLocationTrackingModeActivity","MyLocationToggleActivity","MyLocationTintActivity","MyLocationDrawableActivity","DoubleMapActivity", "LocationPickerActivity","GeoJsonClusteringActivity","RuntimeStyleTestActivity", "AnimatedMarkerActivity", "ViewPagerActivity","MapFragmentActivity","SupportMapFragmentActivity","SnapshotActivity","NavigationDrawerActivity", "QueryRenderedFeaturesBoxHighlightActivity", "MultiMapActivity", "MapInDialogActivity", "SimpleMapActivity"];
const appBasePath = 'platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity';
const testBasePath = 'platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen';
const subPackages = fs.readdirSync(appBasePath);
diff --git a/platform/android/scripts/metrics.sh b/platform/android/scripts/metrics.sh
new file mode 100755
index 0000000000..37d8c1de65
--- /dev/null
+++ b/platform/android/scripts/metrics.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+set -e
+set -o pipefail
+
+# Track individual architectures
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/src/main/jniLibs/armeabi/libmapbox-gl.so" "Platform=Android,Arch=arm-v5"
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/src/main/jniLibs/armeabi-v7a/libmapbox-gl.so" "Platform=Android,Arch=arm-v7"
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/src/main/jniLibs/arm64-v8a/libmapbox-gl.so" "Platform=Android,Arch=arm-v8"
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/src/main/jniLibs/x86/libmapbox-gl.so" "Platform=Android,Arch=x86"
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/src/main/jniLibs/x86_64/libmapbox-gl.so" "Platform=Android,Arch=x86_64"
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/src/main/jniLibs/mips/libmapbox-gl.so" "Platform=Android,Arch=mips"
+
+# Track overall library size
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/build/outputs/aar/MapboxGLAndroidSDK-release.aar" "Platform=Android,Arch=Archive"
diff --git a/platform/android/src/connectivity_listener.cpp b/platform/android/src/connectivity_listener.cpp
index df5c60a485..cc2f0a4a81 100644
--- a/platform/android/src/connectivity_listener.cpp
+++ b/platform/android/src/connectivity_listener.cpp
@@ -1,7 +1,7 @@
#include "connectivity_listener.hpp"
#include <mbgl/storage/network_status.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <jni/jni.hpp>
diff --git a/platform/android/src/example_custom_layer.cpp b/platform/android/src/example_custom_layer.cpp
index 516a8f2cd5..c55c9c3527 100644
--- a/platform/android/src/example_custom_layer.cpp
+++ b/platform/android/src/example_custom_layer.cpp
@@ -1,14 +1,17 @@
#include <jni.h>
#include <GLES2/gl2.h>
+#include <mbgl/util/logging.hpp>
+
#include <mbgl/style/layers/custom_layer.hpp>
static const GLchar * vertexShaderSource = "attribute vec2 a_pos; void main() { gl_Position = vec4(a_pos, 0, 1); }";
-static const GLchar * fragmentShaderSource = "void main() { gl_FragColor = vec4(0, 1, 0, 1); }";
+static const GLchar * fragmentShaderSource = "uniform vec4 fill_color; void main() { gl_FragColor = fill_color; }";
class ExampleCustomLayer {
public:
~ExampleCustomLayer() {
+ mbgl::Log::Info(mbgl::Event::General, "~ExampleCustomLayer");
if (program) {
glDeleteBuffers(1, &buffer);
glDetachShader(program, vertexShader);
@@ -20,6 +23,7 @@ public:
}
void initialize() {
+ mbgl::Log::Info(mbgl::Event::General, "Initialize");
program = glCreateProgram();
vertexShader = glCreateShader(GL_VERTEX_SHADER);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
@@ -32,6 +36,7 @@ public:
glAttachShader(program, fragmentShader);
glLinkProgram(program);
a_pos = glGetAttribLocation(program, "a_pos");
+ fill_color = glGetUniformLocation(program, "fill_color");
GLfloat background[] = { -1,-1, 1,-1, -1,1, 1,1 };
glGenBuffers(1, &buffer);
@@ -40,12 +45,15 @@ public:
}
void render() {
+ mbgl::Log::Info(mbgl::Event::General, "Render");
glUseProgram(program);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glEnableVertexAttribArray(a_pos);
glVertexAttribPointer(a_pos, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glDisable(GL_STENCIL_TEST);
glDisable(GL_DEPTH_TEST);
+ glUniform4fv(fill_color, 1, color);
+
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
@@ -54,35 +62,54 @@ public:
GLuint fragmentShader = 0;
GLuint buffer = 0;
GLuint a_pos = 0;
+ GLuint fill_color = 0;
+
+ static GLfloat color[];
};
+GLfloat ExampleCustomLayer::color[] = { 0.0f, 1.0f, 0.0f, 1.0f };
+
jlong JNICALL nativeCreateContext(JNIEnv*, jobject) {
- return reinterpret_cast<jlong>(new ExampleCustomLayer());
+ mbgl::Log::Info(mbgl::Event::General, "nativeCreateContext");
+ return reinterpret_cast<jlong>(new ExampleCustomLayer());
+}
+
+void JNICALL nativeSetColor(JNIEnv*, jobject, jfloat red, jfloat green, jfloat blue, jfloat alpha) {
+ mbgl::Log::Info(mbgl::Event::General, "nativeSetColor: %.2f, %.2f, %.2f, %.2f", red, green, blue, alpha);
+ ExampleCustomLayer::color[0] = red;
+ ExampleCustomLayer::color[1] = green;
+ ExampleCustomLayer::color[2] = blue;
+ ExampleCustomLayer::color[3] = alpha;
}
void nativeInitialize(void *context) {
+ mbgl::Log::Info(mbgl::Event::General, "nativeInitialize");
reinterpret_cast<ExampleCustomLayer*>(context)->initialize();
}
void nativeRender(void *context, const mbgl::style::CustomLayerRenderParameters& /*parameters*/) {
+ mbgl::Log::Info(mbgl::Event::General, "nativeRender");
reinterpret_cast<ExampleCustomLayer*>(context)->render();
}
void nativeDenitialize(void *context) {
+ mbgl::Log::Info(mbgl::Event::General, "nativeDeinitialize");
delete reinterpret_cast<ExampleCustomLayer*>(context);
}
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
+ mbgl::Log::Info(mbgl::Event::General, "OnLoad");
JNIEnv *env = nullptr;
vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
jclass customLayerClass = env->FindClass("com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer");
JNINativeMethod methods[] = {
- {"createContext", "()J", reinterpret_cast<void *>(&nativeCreateContext)}
+ {"createContext", "()J", reinterpret_cast<void *>(&nativeCreateContext)},
+ {"setColor", "(FFFF)V", reinterpret_cast<void *>(&nativeSetColor)}
};
- if (env->RegisterNatives(customLayerClass, methods, 1) < 0) {
+ if (env->RegisterNatives(customLayerClass, methods, 2) < 0) {
env->ExceptionDescribe();
return JNI_ERR;
}
diff --git a/platform/android/src/geometry/conversion/feature.hpp b/platform/android/src/geometry/conversion/feature.hpp
index 9f75b9c8f1..f0c77c3389 100644
--- a/platform/android/src/geometry/conversion/feature.hpp
+++ b/platform/android/src/geometry/conversion/feature.hpp
@@ -16,7 +16,7 @@
#include <vector>
#include <sstream>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
namespace mbgl {
namespace android {
diff --git a/platform/android/src/http_file_source.cpp b/platform/android/src/http_file_source.cpp
index ed4d81391f..ee1429bd74 100644
--- a/platform/android/src/http_file_source.cpp
+++ b/platform/android/src/http_file_source.cpp
@@ -1,7 +1,7 @@
#include <mbgl/storage/http_file_source.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/util.hpp>
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index 6dcd177cd6..5182e268f3 100755
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -25,8 +25,8 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/source.hpp>
#include <mbgl/sprite/sprite_image.hpp>
-#include <mbgl/platform/event.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/event.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/util/optional.hpp>
@@ -431,6 +431,12 @@ void nativeSetStyleUrl(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, j
nativeMapView->getMap().setStyleURL(std_string_from_jstring(env, url));
}
+jni::jstring* nativeGetStyleUrl(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr){
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
+ return std_string_to_jstring(env, nativeMapView->getMap().getStyleURL());
+}
+
void nativeSetStyleJson(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* newStyleJson) {
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
@@ -471,8 +477,7 @@ void nativeMoveBy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdoubl
jlong duration) {
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::ScreenCoordinate center(dx, dy);
- nativeMapView->getMap().moveBy(center, mbgl::Milliseconds(duration));
+ nativeMapView->getMap().moveBy({dx, dy}, mbgl::Milliseconds(duration));
}
void nativeSetLatLng(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble latitude, jdouble longitude, jlong duration) {
@@ -498,7 +503,7 @@ jdoubleArray nativeGetCameraValues(JNIEnv *env, jni::jobject* obj, jlong nativeM
jdouble buf[5];
buf[0] = latLng.latitude;
buf[1] = latLng.longitude;
- buf[2] = -(nativeMapView->getMap().getBearing()-360);
+ buf[2] = -nativeMapView->getMap().getBearing();
buf[3] = nativeMapView->getMap().getPitch();
buf[4] = nativeMapView->getMap().getZoom();
env->SetDoubleArrayRegion(output, start, leng, buf);
@@ -833,9 +838,10 @@ void nativeAddAnnotationIcon(JNIEnv *env, jni::jobject* obj, jlong nativeMapView
NullCheck(*env, jpixels);
std::size_t size = jni::GetArrayLength(*env, *jpixels);
- mbgl::PremultipliedImage premultipliedImage(width, height);
+ mbgl::PremultipliedImage premultipliedImage(
+ { static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
- if (premultipliedImage.size() != uint32_t(size)) {
+ if (premultipliedImage.bytes() != uint32_t(size)) {
throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
}
@@ -1007,7 +1013,7 @@ void nativeJumpTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdoubl
mbgl::CameraOptions options;
if (angle != -1) {
- options.angle = angle * M_PI / 180;
+ options.angle = (-angle * M_PI) / 180;
}
options.center = mbgl::LatLng(latitude, longitude);
options.padding = nativeMapView->getInsets();
@@ -1027,7 +1033,7 @@ void nativeEaseTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdoubl
mbgl::CameraOptions cameraOptions;
if (angle != -1) {
- cameraOptions.angle = angle * M_PI / 180;
+ cameraOptions.angle = (-angle * M_PI) / 180;
}
cameraOptions.center = mbgl::LatLng(latitude, longitude);
cameraOptions.padding = nativeMapView->getInsets();
@@ -1060,7 +1066,7 @@ void nativeFlyTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble
mbgl::CameraOptions cameraOptions;
if (angle != -1) {
- cameraOptions.angle = angle * M_PI / 180 ;
+ cameraOptions.angle = (-angle * M_PI) / 180 ;
}
cameraOptions.center = mbgl::LatLng(latitude, longitude);
cameraOptions.padding = nativeMapView->getInsets();
@@ -1099,15 +1105,19 @@ void nativeAddLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlon
assert(nativeLayerPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- Layer *layer = reinterpret_cast<Layer *>(nativeLayerPtr);
- nativeMapView->getMap().addLayer(
- layer->releaseCoreLayer(),
- before ? mbgl::optional<std::string>(std_string_from_jstring(env, before)) : mbgl::optional<std::string>()
- );
+ Layer *layer = reinterpret_cast<Layer *>(nativeLayerPtr);
+ try {
+ layer->addToMap(nativeMapView->getMap(), before ? mbgl::optional<std::string>(std_string_from_jstring(env, before)) : mbgl::optional<std::string>());
+ } catch (const std::runtime_error& error) {
+ jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/layers/CannotAddLayerException"), error.what());
+ }
}
-void nativeRemoveLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
+/**
+ * Remove by layer id. Ownership is not transferred back
+ */
+void nativeRemoveLayerById(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
try {
@@ -1117,6 +1127,22 @@ void nativeRemoveLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, j
}
}
+/**
+ * Remove with wrapper object id. Ownership is transferred back to the wrapper
+ */
+void nativeRemoveLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong layerPtr) {
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
+ mbgl::android::Layer *layer = reinterpret_cast<mbgl::android::Layer *>(layerPtr);
+ try {
+ std::unique_ptr<mbgl::style::Layer> coreLayer = nativeMapView->getMap().removeLayer(layer->get().getID());
+ layer->setLayer(std::move(coreLayer));
+ } catch (const std::runtime_error& error) {
+ jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/layers/NoSuchLayerException"), error.what());
+ }
+}
+
+
jni::jobject* nativeGetSource(JNIEnv *env, jni::jobject* obj, jni::jlong nativeMapViewPtr, jni::jstring* sourceId) {
assert(env);
assert(nativeMapViewPtr != 0);
@@ -1140,16 +1166,32 @@ void nativeAddSource(JNIEnv *env, jni::jobject* obj, jni::jlong nativeMapViewPtr
assert(nativeSourcePtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
+
Source *source = reinterpret_cast<Source *>(nativeSourcePtr);
+ try {
+ source->addToMap(nativeMapView->getMap());
+ } catch (const std::runtime_error& error) {
+ jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/sources/CannotAddSourceException"), error.what());
+ }
+}
- nativeMapView->getMap().addSource(source->releaseCoreSource());
+void nativeRemoveSourceById(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
+ try {
+ nativeMapView->getMap().removeSource(std_string_from_jstring(env, id));
+ } catch (const std::runtime_error& error) {
+ jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/sources/NoSuchSourceException"), error.what());
+ }
}
-void nativeRemoveSource(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
+void nativeRemoveSource(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong sourcePtr) {
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
+ mbgl::android::Source *source = reinterpret_cast<mbgl::android::Source *>(sourcePtr);
try {
- nativeMapView->getMap().removeSource(std_string_from_jstring(env, id));
+ std::unique_ptr<mbgl::style::Source> coreSource = nativeMapView->getMap().removeSource(source->get().getID());
+ source->setSource(std::move(coreSource));
} catch (const std::runtime_error& error) {
jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/sources/NoSuchSourceException"), error.what());
}
@@ -1162,9 +1204,10 @@ void nativeAddImage(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni:
// Create Pre-multiplied image from byte[]
NullCheck(*env, data);
std::size_t size = jni::GetArrayLength(*env, *data);
- mbgl::PremultipliedImage premultipliedImage(width, height);
+ mbgl::PremultipliedImage premultipliedImage(
+ { static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
- if (premultipliedImage.size() != uint32_t(size)) {
+ if (premultipliedImage.bytes() != uint32_t(size)) {
throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
}
@@ -1666,9 +1709,12 @@ void updateOfflineRegionMetadata(JNIEnv *env, jni::jobject* offlineRegion_, jni:
// Offline calls end
-}
+} // anonymous
-extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+namespace mbgl {
+namespace android {
+
+void registerNatives(JavaVM *vm) {
theJVM = vm;
jni::JNIEnv& env = jni::GetEnv(*vm, jni::jni_version_1_6);
@@ -1776,6 +1822,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
MAKE_NATIVE_METHOD(nativeSetClasses, "(JLjava/util/List;)V"),
MAKE_NATIVE_METHOD(nativeGetClasses, "(J)Ljava/util/List;"),
MAKE_NATIVE_METHOD(nativeSetStyleUrl, "(JLjava/lang/String;)V"),
+ MAKE_NATIVE_METHOD(nativeGetStyleUrl, "(J)Ljava/lang/String;"),
MAKE_NATIVE_METHOD(nativeSetStyleJson, "(JLjava/lang/String;)V"),
MAKE_NATIVE_METHOD(nativeGetStyleJson, "(J)Ljava/lang/String;"),
MAKE_NATIVE_METHOD(nativeSetAccessToken, "(JLjava/lang/String;)V"),
@@ -1831,10 +1878,12 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
MAKE_NATIVE_METHOD(nativeFlyTo, "(JDDDJDD)V"),
MAKE_NATIVE_METHOD(nativeGetLayer, "(JLjava/lang/String;)Lcom/mapbox/mapboxsdk/style/layers/Layer;"),
MAKE_NATIVE_METHOD(nativeAddLayer, "(JJLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeRemoveLayer, "(JLjava/lang/String;)V"),
+ MAKE_NATIVE_METHOD(nativeRemoveLayerById, "(JLjava/lang/String;)V"),
+ MAKE_NATIVE_METHOD(nativeRemoveLayer, "(JJ)V"),
MAKE_NATIVE_METHOD(nativeGetSource, "(JLjava/lang/String;)Lcom/mapbox/mapboxsdk/style/sources/Source;"),
MAKE_NATIVE_METHOD(nativeAddSource, "(JJ)V"),
- MAKE_NATIVE_METHOD(nativeRemoveSource, "(JLjava/lang/String;)V"),
+ MAKE_NATIVE_METHOD(nativeRemoveSourceById, "(JLjava/lang/String;)V"),
+ MAKE_NATIVE_METHOD(nativeRemoveSource, "(JJ)V"),
MAKE_NATIVE_METHOD(nativeAddImage, "(JLjava/lang/String;IIF[B)V"),
MAKE_NATIVE_METHOD(nativeRemoveImage, "(JLjava/lang/String;)V"),
MAKE_NATIVE_METHOD(nativeSetContentPadding, "(JDDDD)V"),
@@ -1949,6 +1998,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
char release[PROP_VALUE_MAX] = "";
__system_property_get("ro.build.version.release", release);
androidRelease = std::string(release);
-
- return JNI_VERSION_1_6;
}
+
+} // android
+} // mbgl
diff --git a/platform/android/src/jni.hpp b/platform/android/src/jni.hpp
index 0810ee656d..90ec914cf2 100644
--- a/platform/android/src/jni.hpp
+++ b/platform/android/src/jni.hpp
@@ -23,6 +23,8 @@ extern jmethodID onSnapshotReadyId;
extern bool attach_jni_thread(JavaVM* vm, JNIEnv** env, std::string threadName);
extern void detach_jni_thread(JavaVM* vm, JNIEnv** env, bool detach);
+
+extern void registerNatives(JavaVM* vm);
-}
-}
+} //android
+} //mbgl
diff --git a/platform/android/src/log_android.cpp b/platform/android/src/logging_android.cpp
index e5c8cfd812..2e025c059f 100644
--- a/platform/android/src/log_android.cpp
+++ b/platform/android/src/logging_android.cpp
@@ -1,4 +1,4 @@
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <android/log.h>
diff --git a/platform/android/src/main.cpp b/platform/android/src/main.cpp
new file mode 100644
index 0000000000..03a8288719
--- /dev/null
+++ b/platform/android/src/main.cpp
@@ -0,0 +1,9 @@
+#include "jni.hpp"
+#include <jni/jni.hpp>
+
+extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *) {
+ assert(vm != nullptr);
+ mbgl::android::registerNatives(vm);
+ return JNI_VERSION_1_6;
+}
+
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 84daf82e8b..8234b74af2 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -10,13 +10,10 @@
#include <sys/system_properties.h>
-#include <GLES2/gl2.h>
-
-#include <mbgl/platform/platform.hpp>
-#include <mbgl/platform/event.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/platform.hpp>
+#include <mbgl/util/event.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/gl/extension.hpp>
-#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/image.hpp>
@@ -40,23 +37,6 @@ void log_egl_string(EGLDisplay display, EGLint name, const char *label) {
}
}
-void log_gl_string(GLenum name, const char *label) {
- const GLubyte *str = glGetString(name);
- if (str == nullptr) {
- mbgl::Log::Error(mbgl::Event::OpenGL, "glGetString(%d) returned error %d", name,
- glGetError());
- throw std::runtime_error("glGetString() failed");
- } else {
- char buf[513];
- for (int len = std::strlen(reinterpret_cast<const char *>(str)), pos = 0; len > 0;
- len -= 512, pos += 512) {
- strncpy(buf, reinterpret_cast<const char *>(str) + pos, 512);
- buf[512] = 0;
- mbgl::Log::Info(mbgl::Event::OpenGL, "GL %s: %s", label, buf);
- }
- }
-}
-
NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float pixelRatio, int availableProcessors_, size_t totalMemory_)
: env(env_),
availableProcessors(availableProcessors_),
@@ -83,15 +63,14 @@ NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float pixelRatio, int a
mbgl::android::apkPath);
map = std::make_unique<mbgl::Map>(
- *this,
- std::array<uint16_t, 2>{{ static_cast<uint16_t>(width), static_cast<uint16_t>(height) }},
+ *this, mbgl::Size{ static_cast<uint32_t>(width), static_cast<uint32_t>(height) },
pixelRatio, *fileSource, threadPool, MapMode::Continuous);
float zoomFactor = map->getMaxZoom() - map->getMinZoom() + 1;
float cpuFactor = availableProcessors;
float memoryFactor = static_cast<float>(totalMemory) / 1000.0f / 1000.0f / 1000.0f;
- float sizeFactor = (static_cast<float>(map->getWidth()) / mbgl::util::tileSize) *
- (static_cast<float>(map->getHeight()) / mbgl::util::tileSize);
+ float sizeFactor = (static_cast<float>(map->getSize().width) / mbgl::util::tileSize) *
+ (static_cast<float>(map->getSize().height) / mbgl::util::tileSize);
size_t cacheSize = zoomFactor * cpuFactor * memoryFactor * sizeFactor * 0.5f;
@@ -117,14 +96,20 @@ NativeMapView::~NativeMapView() {
vm = nullptr;
}
+mbgl::Size NativeMapView::getFramebufferSize() const {
+ return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) };
+}
+
void NativeMapView::updateViewBinding() {
getContext().bindFramebuffer.setCurrentValue(0);
- getContext().viewport.setCurrentValue({ 0, 0, static_cast<uint16_t>(fbWidth), static_cast<uint16_t>(fbHeight) });
+ assert(mbgl::gl::value::BindFramebuffer::Get() == getContext().bindFramebuffer.getCurrentValue());
+ getContext().viewport.setCurrentValue({ 0, 0, getFramebufferSize() });
+ assert(mbgl::gl::value::Viewport::Get() == getContext().viewport.getCurrentValue());
}
void NativeMapView::bind() {
getContext().bindFramebuffer = 0;
- getContext().viewport = { 0, 0, static_cast<uint16_t>(fbWidth), static_cast<uint16_t>(fbHeight) };
+ getContext().viewport = { 0, 0, getFramebufferSize() };
}
void NativeMapView::activate() {
@@ -192,6 +177,11 @@ void NativeMapView::invalidate() {
void NativeMapView::render() {
BackendScope guard(*this);
+ if (framebufferSizeChanged) {
+ getContext().viewport = { 0, 0, getFramebufferSize() };
+ framebufferSizeChanged = false;
+ }
+
updateViewBinding();
map->render(*this);
@@ -199,18 +189,7 @@ void NativeMapView::render() {
snapshot = false;
// take snapshot
- const unsigned int w = fbWidth;
- const unsigned int h = fbHeight;
- mbgl::PremultipliedImage image { static_cast<uint16_t>(w), static_cast<uint16_t>(h) };
- MBGL_CHECK_ERROR(glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
- const size_t stride = image.stride();
- auto tmp = std::make_unique<uint8_t[]>(stride);
- uint8_t *rgba = image.data.get();
- for (int i = 0, j = h - 1; i < j; i++, j--) {
- std::memcpy(tmp.get(), rgba + i * stride, stride);
- std::memcpy(rgba + i * stride, rgba + j * stride, stride);
- std::memcpy(rgba + j * stride, tmp.get(), stride);
- }
+ auto image = getContext().readFramebuffer<mbgl::PremultipliedImage>(getFramebufferSize());
// encode and convert to jbytes
std::string string = encodePNG(image);
@@ -241,13 +220,6 @@ mbgl::Map &NativeMapView::getMap() { return *map; }
mbgl::DefaultFileSource &NativeMapView::getFileSource() { return *fileSource; }
-bool NativeMapView::inEmulator() {
- // Detect if we are in emulator
- char prop[PROP_VALUE_MAX];
- __system_property_get("ro.kernel.qemu", prop);
- return strtol(prop, nullptr, 0) == 1;
-}
-
void NativeMapView::initializeDisplay() {
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::initializeDisplay");
@@ -277,22 +249,39 @@ void NativeMapView::initializeDisplay() {
log_egl_string(display, EGL_CLIENT_APIS, "Client APIs");
log_egl_string(display, EGL_EXTENSIONS, "Client Extensions");
- // Detect if we are in emulator
- if (inEmulator()) {
+ // Detect if we are in emulator.
+ const bool inEmulator = []() {
+ char prop[PROP_VALUE_MAX];
+ __system_property_get("ro.kernel.qemu", prop);
+ return strtol(prop, nullptr, 0) == 1;
+ }();
+
+ if (inEmulator) {
+ // XXX https://code.google.com/p/android/issues/detail?id=78977
mbgl::Log::Warning(mbgl::Event::Android, "In emulator! Enabling hacks :-(");
}
+ if (!eglBindAPI(EGL_OPENGL_ES_API)) {
+ mbgl::Log::Error(mbgl::Event::OpenGL, "eglBindAPI(EGL_OPENGL_ES_API) returned error %d", eglGetError());
+ throw std::runtime_error("eglBindAPI() failed");
+ }
+
// Get all configs at least RGB 565 with 16 depth and 8 stencil
EGLint configAttribs[] = {
- EGL_CONFIG_CAVEAT, EGL_NONE, EGL_RENDERABLE_TYPE,
- EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_BUFFER_SIZE, 16, EGL_RED_SIZE,
- 5, EGL_GREEN_SIZE, 6,
- EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE,
- 16, EGL_STENCIL_SIZE, 8,
- (inEmulator() ? EGL_NONE : EGL_CONFORMANT), EGL_OPENGL_ES2_BIT, // Ugly hack
- (inEmulator() ? EGL_NONE : EGL_COLOR_BUFFER_TYPE), EGL_RGB_BUFFER, // Ugly hack
- EGL_NONE};
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_BUFFER_SIZE, 16,
+ EGL_RED_SIZE, 5,
+ EGL_GREEN_SIZE, 6,
+ EGL_BLUE_SIZE, 5,
+ EGL_DEPTH_SIZE, 16,
+ EGL_STENCIL_SIZE, 8,
+ (inEmulator ? EGL_NONE : EGL_CONFORMANT), EGL_OPENGL_ES2_BIT,
+ (inEmulator ? EGL_NONE : EGL_COLOR_BUFFER_TYPE), EGL_RGB_BUFFER,
+ EGL_NONE
+ };
+
EGLint numConfigs;
if (!eglChooseConfig(display, configAttribs, nullptr, 0, &numConfigs)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglChooseConfig(NULL) returned error %d",
@@ -427,16 +416,6 @@ void NativeMapView::createSurface(ANativeWindow *window_) {
throw std::runtime_error("eglMakeCurrent() failed");
}
- log_gl_string(GL_VENDOR, "Vendor");
- log_gl_string(GL_RENDERER, "Renderer");
- log_gl_string(GL_VERSION, "Version");
- if (!inEmulator()) {
- log_gl_string(GL_SHADING_LANGUAGE_VERSION,
- "SL Version"); // In the emulator this returns NULL with error code 0?
- // https://code.google.com/p/android/issues/detail?id=78977
- }
-
- log_gl_string(GL_EXTENSIONS, "Extensions");
mbgl::gl::InitializeExtensions([] (const char * name) {
return reinterpret_cast<mbgl::gl::glProc>(eglGetProcAddress(name));
});
@@ -714,12 +693,13 @@ void NativeMapView::updateFps() {
void NativeMapView::resizeView(int w, int h) {
width = w;
height = h;
- map->setSize({{ static_cast<uint16_t>(width), static_cast<uint16_t>(height) }});
+ map->setSize({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
}
void NativeMapView::resizeFramebuffer(int w, int h) {
fbWidth = w;
fbHeight = h;
+ framebufferSizeChanged = true;
invalidate();
}
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index 00cb6e591e..e7379700a9 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -4,7 +4,7 @@
#include <mbgl/map/view.hpp>
#include <mbgl/map/backend.hpp>
#include <mbgl/util/noncopyable.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <string>
@@ -20,6 +20,7 @@ public:
NativeMapView(JNIEnv *env, jobject obj, float pixelRatio, int availableProcessors, size_t totalMemory);
virtual ~NativeMapView();
+ mbgl::Size getFramebufferSize() const;
void updateViewBinding();
void bind() override;
@@ -58,8 +59,6 @@ protected:
private:
EGLConfig chooseConfig(const EGLConfig configs[], EGLint numConfigs);
- bool inEmulator();
-
private:
JavaVM *vm = nullptr;
JNIEnv *env = nullptr;
@@ -91,6 +90,7 @@ private:
int height = 0;
int fbWidth = 0;
int fbHeight = 0;
+ bool framebufferSizeChanged = true;
int availableProcessors = 0;
size_t totalMemory = 0;
diff --git a/platform/android/src/run_loop.cpp b/platform/android/src/run_loop.cpp
index 1e5fc9b4ba..170b05c23c 100644
--- a/platform/android/src/run_loop.cpp
+++ b/platform/android/src/run_loop.cpp
@@ -1,6 +1,6 @@
#include "run_loop_impl.hpp"
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/platform.hpp>
#include <mbgl/util/thread_context.hpp>
#include <mbgl/util/thread_local.hpp>
#include <mbgl/util/timer.hpp>
diff --git a/platform/android/src/style/android_conversion.hpp b/platform/android/src/style/android_conversion.hpp
index cea7ce6d2a..de0ac91502 100644
--- a/platform/android/src/style/android_conversion.hpp
+++ b/platform/android/src/style/android_conversion.hpp
@@ -2,7 +2,7 @@
#include "value.hpp"
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/util/optional.hpp>
diff --git a/platform/android/src/style/conversion/geojson.hpp b/platform/android/src/style/conversion/geojson.hpp
index 920c670fcb..6bc48b3700 100644
--- a/platform/android/src/style/conversion/geojson.hpp
+++ b/platform/android/src/style/conversion/geojson.hpp
@@ -6,7 +6,7 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/util/rapidjson.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <jni/jni.hpp>
#include <sstream>
diff --git a/platform/android/src/style/conversion/types.hpp b/platform/android/src/style/conversion/types.hpp
index d3c12ff89a..1c433bb264 100644
--- a/platform/android/src/style/conversion/types.hpp
+++ b/platform/android/src/style/conversion/types.hpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#pragma once
#include "types_string_values.hpp"
diff --git a/platform/android/src/style/conversion/types.hpp.ejs b/platform/android/src/style/conversion/types.hpp.ejs
index de26d061f7..d248d42b72 100644
--- a/platform/android/src/style/conversion/types.hpp.ejs
+++ b/platform/android/src/style/conversion/types.hpp.ejs
@@ -1,7 +1,7 @@
<%
const properties = locals.properties;
-%>
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#pragma once
#include "types_string_values.hpp"
diff --git a/platform/android/src/style/conversion/types_string_values.hpp b/platform/android/src/style/conversion/types_string_values.hpp
index b42ca52acd..9f21a2fed9 100644
--- a/platform/android/src/style/conversion/types_string_values.hpp
+++ b/platform/android/src/style/conversion/types_string_values.hpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#pragma once
#include <mbgl/style/types.hpp>
diff --git a/platform/android/src/style/conversion/types_string_values.hpp.ejs b/platform/android/src/style/conversion/types_string_values.hpp.ejs
index 39021d390d..c1646baa1a 100644
--- a/platform/android/src/style/conversion/types_string_values.hpp.ejs
+++ b/platform/android/src/style/conversion/types_string_values.hpp.ejs
@@ -1,7 +1,7 @@
<%
const properties = locals.properties;
-%>
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#pragma once
#include <mbgl/style/types.hpp>
diff --git a/platform/android/src/style/layers/background_layer.cpp b/platform/android/src/style/layers/background_layer.cpp
index 25526a07fa..021ac947ad 100644
--- a/platform/android/src/style/layers/background_layer.cpp
+++ b/platform/android/src/style/layers/background_layer.cpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#include "background_layer.hpp"
diff --git a/platform/android/src/style/layers/background_layer.hpp b/platform/android/src/style/layers/background_layer.hpp
index f201213e46..bd62c024f4 100644
--- a/platform/android/src/style/layers/background_layer.hpp
+++ b/platform/android/src/style/layers/background_layer.hpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#pragma once
diff --git a/platform/android/src/style/layers/circle_layer.cpp b/platform/android/src/style/layers/circle_layer.cpp
index c2d6ff06d1..4a6ba95d31 100644
--- a/platform/android/src/style/layers/circle_layer.cpp
+++ b/platform/android/src/style/layers/circle_layer.cpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#include "circle_layer.hpp"
@@ -63,6 +63,24 @@ namespace android {
return jni::Object<jni::ObjectTag>(*converted);
}
+ jni::Object<jni::ObjectTag> CircleLayer::getCircleStrokeWidth(jni::JNIEnv& env) {
+ using namespace mbgl::android::conversion;
+ Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeWidth());
+ return jni::Object<jni::ObjectTag>(*converted);
+ }
+
+ jni::Object<jni::ObjectTag> CircleLayer::getCircleStrokeColor(jni::JNIEnv& env) {
+ using namespace mbgl::android::conversion;
+ Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeColor());
+ return jni::Object<jni::ObjectTag>(*converted);
+ }
+
+ jni::Object<jni::ObjectTag> CircleLayer::getCircleStrokeOpacity(jni::JNIEnv& env) {
+ using namespace mbgl::android::conversion;
+ Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeOpacity());
+ return jni::Object<jni::ObjectTag>(*converted);
+ }
+
jni::Class<CircleLayer> CircleLayer::javaClass;
jni::jobject* CircleLayer::createJavaPeer(jni::JNIEnv& env) {
@@ -88,7 +106,10 @@ namespace android {
METHOD(&CircleLayer::getCircleOpacity, "nativeGetCircleOpacity"),
METHOD(&CircleLayer::getCircleTranslate, "nativeGetCircleTranslate"),
METHOD(&CircleLayer::getCircleTranslateAnchor, "nativeGetCircleTranslateAnchor"),
- METHOD(&CircleLayer::getCirclePitchScale, "nativeGetCirclePitchScale"));
+ METHOD(&CircleLayer::getCirclePitchScale, "nativeGetCirclePitchScale"),
+ METHOD(&CircleLayer::getCircleStrokeWidth, "nativeGetCircleStrokeWidth"),
+ METHOD(&CircleLayer::getCircleStrokeColor, "nativeGetCircleStrokeColor"),
+ METHOD(&CircleLayer::getCircleStrokeOpacity, "nativeGetCircleStrokeOpacity"));
}
} // namespace android
diff --git a/platform/android/src/style/layers/circle_layer.hpp b/platform/android/src/style/layers/circle_layer.hpp
index 91c99c686e..d45984f23b 100644
--- a/platform/android/src/style/layers/circle_layer.hpp
+++ b/platform/android/src/style/layers/circle_layer.hpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#pragma once
@@ -39,6 +39,12 @@ public:
jni::Object<jni::ObjectTag> getCirclePitchScale(jni::JNIEnv&);
+ jni::Object<jni::ObjectTag> getCircleStrokeWidth(jni::JNIEnv&);
+
+ jni::Object<jni::ObjectTag> getCircleStrokeColor(jni::JNIEnv&);
+
+ jni::Object<jni::ObjectTag> getCircleStrokeOpacity(jni::JNIEnv&);
+
jni::jobject* createJavaPeer(jni::JNIEnv&);
}; // class CircleLayer
diff --git a/platform/android/src/style/layers/custom_layer.cpp b/platform/android/src/style/layers/custom_layer.cpp
index 6568455c67..d5d330a019 100644
--- a/platform/android/src/style/layers/custom_layer.cpp
+++ b/platform/android/src/style/layers/custom_layer.cpp
@@ -2,7 +2,7 @@
#include <string>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
namespace mbgl {
namespace android {
diff --git a/platform/android/src/style/layers/fill_layer.cpp b/platform/android/src/style/layers/fill_layer.cpp
index 8cb96c9cd3..84d47b6afe 100644
--- a/platform/android/src/style/layers/fill_layer.cpp
+++ b/platform/android/src/style/layers/fill_layer.cpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#include "fill_layer.hpp"
diff --git a/platform/android/src/style/layers/fill_layer.hpp b/platform/android/src/style/layers/fill_layer.hpp
index 5dbd7a3412..7609a5742f 100644
--- a/platform/android/src/style/layers/fill_layer.hpp
+++ b/platform/android/src/style/layers/fill_layer.hpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#pragma once
diff --git a/platform/android/src/style/layers/layer.cpp b/platform/android/src/style/layers/layer.cpp
index 3c1fc0af62..c0c57c839d 100644
--- a/platform/android/src/style/layers/layer.cpp
+++ b/platform/android/src/style/layers/layer.cpp
@@ -3,7 +3,7 @@
#include <jni/jni.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
//Java -> C++ conversion
#include <mbgl/style/conversion.hpp>
@@ -32,8 +32,21 @@ namespace android {
Layer::~Layer() {
}
- jni::String Layer::getId(jni::JNIEnv& env) {
- return jni::Make<jni::String>(env, layer.getID());
+ void Layer::addToMap(mbgl::Map& _map, mbgl::optional<std::string> before) {
+ //Check to see if we own the layer first
+ if (!ownedLayer) {
+ throw std::runtime_error("Cannot add layer twice");
+ }
+
+ //Add layer to map
+ _map.addLayer(releaseCoreLayer(), before);
+
+ //Save pointer to the map
+ this->map = &_map;
+ }
+
+ void Layer::setLayer(std::unique_ptr<mbgl::style::Layer> sourceLayer) {
+ this->ownedLayer = std::move(sourceLayer);
}
std::unique_ptr<mbgl::style::Layer> Layer::releaseCoreLayer() {
@@ -41,6 +54,14 @@ namespace android {
return std::move(ownedLayer);
}
+ jni::String Layer::getId(jni::JNIEnv& env) {
+ return jni::Make<jni::String>(env, layer.getID());
+ }
+
+ style::Layer& Layer::get() {
+ return layer;
+ }
+
void Layer::setLayoutProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) {
Value value(env, jvalue);
diff --git a/platform/android/src/style/layers/layer.cpp.ejs b/platform/android/src/style/layers/layer.cpp.ejs
index 68dd27b801..500c76ea7a 100644
--- a/platform/android/src/style/layers/layer.cpp.ejs
+++ b/platform/android/src/style/layers/layer.cpp.ejs
@@ -2,9 +2,9 @@
const type = locals.type;
const properties = locals.properties;
-%>
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
-#include "<%- type %>_layer.hpp"
+#include "<%- type.replace('-', '_') %>_layer.hpp"
#include <string>
diff --git a/platform/android/src/style/layers/layer.hpp b/platform/android/src/style/layers/layer.hpp
index 024a3c38b7..f3cd073552 100644
--- a/platform/android/src/style/layers/layer.hpp
+++ b/platform/android/src/style/layers/layer.hpp
@@ -34,10 +34,16 @@ public:
virtual jni::jobject* createJavaPeer(jni::JNIEnv&) = 0;
+ /**
+ * Set core layer (ie return ownership after remove)
+ */
+ void setLayer(std::unique_ptr<mbgl::style::Layer>);
+
+ void addToMap(mbgl::Map&, mbgl::optional<std::string>);
+
jni::String getId(jni::JNIEnv&);
- //Release the owned view and return it
- std::unique_ptr<mbgl::style::Layer> releaseCoreLayer();
+ style::Layer& get();
void setLayoutProperty(jni::JNIEnv&, jni::String, jni::Object<> value);
@@ -64,8 +70,16 @@ public:
jni::Object<jni::ObjectTag> getVisibility(jni::JNIEnv&);
protected:
+ //Release the owned view and return it
+ std::unique_ptr<mbgl::style::Layer> releaseCoreLayer();
+
+ //Owned layer is set when creating a new layer, before adding it to the map
std::unique_ptr<mbgl::style::Layer> ownedLayer;
+
+ //Raw reference to the layer
mbgl::style::Layer& layer;
+
+ //Map is set when the layer is retrieved or after adding to the map
mbgl::Map* map;
};
diff --git a/platform/android/src/style/layers/layer.hpp.ejs b/platform/android/src/style/layers/layer.hpp.ejs
index 826e133fca..3d715746ff 100644
--- a/platform/android/src/style/layers/layer.hpp.ejs
+++ b/platform/android/src/style/layers/layer.hpp.ejs
@@ -2,12 +2,12 @@
const type = locals.type;
const properties = locals.properties;
-%>
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#pragma once
#include "layer.hpp"
-#include <mbgl/style/layers/<%- type %>_layer.hpp>
+#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp>
#include <jni/jni.hpp>
namespace mbgl {
diff --git a/platform/android/src/style/layers/line_layer.cpp b/platform/android/src/style/layers/line_layer.cpp
index 91d3e4a1cd..2dce8b618a 100644
--- a/platform/android/src/style/layers/line_layer.cpp
+++ b/platform/android/src/style/layers/line_layer.cpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#include "line_layer.hpp"
diff --git a/platform/android/src/style/layers/line_layer.hpp b/platform/android/src/style/layers/line_layer.hpp
index da9b564325..e2fc93329e 100644
--- a/platform/android/src/style/layers/line_layer.hpp
+++ b/platform/android/src/style/layers/line_layer.hpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#pragma once
diff --git a/platform/android/src/style/layers/raster_layer.cpp b/platform/android/src/style/layers/raster_layer.cpp
index da78ccb8e3..25b26155ae 100644
--- a/platform/android/src/style/layers/raster_layer.cpp
+++ b/platform/android/src/style/layers/raster_layer.cpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#include "raster_layer.hpp"
diff --git a/platform/android/src/style/layers/raster_layer.hpp b/platform/android/src/style/layers/raster_layer.hpp
index e59cd05f87..3cc2d96dde 100644
--- a/platform/android/src/style/layers/raster_layer.hpp
+++ b/platform/android/src/style/layers/raster_layer.hpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#pragma once
diff --git a/platform/android/src/style/layers/symbol_layer.cpp b/platform/android/src/style/layers/symbol_layer.cpp
index fd69b6591f..9318d42d5b 100644
--- a/platform/android/src/style/layers/symbol_layer.cpp
+++ b/platform/android/src/style/layers/symbol_layer.cpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#include "symbol_layer.hpp"
diff --git a/platform/android/src/style/layers/symbol_layer.hpp b/platform/android/src/style/layers/symbol_layer.hpp
index f5165327bf..1048b01b14 100644
--- a/platform/android/src/style/layers/symbol_layer.hpp
+++ b/platform/android/src/style/layers/symbol_layer.hpp
@@ -1,4 +1,4 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
#pragma once
diff --git a/platform/android/src/style/sources/source.cpp b/platform/android/src/style/sources/source.cpp
index f3daa777d1..aca7bd6a84 100644
--- a/platform/android/src/style/sources/source.cpp
+++ b/platform/android/src/style/sources/source.cpp
@@ -3,7 +3,7 @@
#include <jni/jni.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
//Java -> C++ conversion
#include <mbgl/style/conversion.hpp>
@@ -31,10 +31,31 @@ namespace android {
Source::~Source() {
}
+ style::Source& Source::get() {
+ return source;
+ }
+
+ void Source::setSource(std::unique_ptr<style::Source> coreSource) {
+ this->ownedSource = std::move(coreSource);
+ }
+
jni::String Source::getId(jni::JNIEnv& env) {
return jni::Make<jni::String>(env, source.getID());
}
+ void Source::addToMap(mbgl::Map& _map) {
+ //Check to see if we own the source first
+ if (!ownedSource) {
+ throw std::runtime_error("Cannot add source twice");
+ }
+
+ //Add source to map
+ _map.addSource(releaseCoreSource());
+
+ //Save pointer to the map
+ this->map = &_map;
+ }
+
std::unique_ptr<mbgl::style::Source> Source::releaseCoreSource() {
assert(ownedSource != nullptr);
return std::move(ownedSource);
diff --git a/platform/android/src/style/sources/source.hpp b/platform/android/src/style/sources/source.hpp
index 0785e4d4e0..0e5d354d93 100644
--- a/platform/android/src/style/sources/source.hpp
+++ b/platform/android/src/style/sources/source.hpp
@@ -32,16 +32,30 @@ public:
virtual ~Source();
+ /**
+ * Set core source (ie return ownership after remove)
+ */
+ void setSource(std::unique_ptr<style::Source>);
+
+ style::Source& get();
+
+ void addToMap(mbgl::Map&);
+
virtual jni::jobject* createJavaPeer(jni::JNIEnv&) = 0;
jni::String getId(jni::JNIEnv&);
+protected:
//Release the owned view and return it
std::unique_ptr<mbgl::style::Source> releaseCoreSource();
-protected:
+ //Set on newly created sources until added to the map
std::unique_ptr<mbgl::style::Source> ownedSource;
+
+ //Raw pointer that is valid until the source is removed from the map
mbgl::style::Source& source;
+
+ //Map pointer is valid for newly created sources only after adding to the map
mbgl::Map* map;
};
diff --git a/platform/android/src/test/Main.java b/platform/android/src/test/Main.java
new file mode 100644
index 0000000000..b6f540f666
--- /dev/null
+++ b/platform/android/src/test/Main.java
@@ -0,0 +1,15 @@
+
+public class Main {
+ public native void runAllTests(String[] args);
+
+ public static void main(String[] args) throws Exception {
+ //Load the tests
+ System.loadLibrary("mbgl-test");
+
+ //Run the tests
+ new Main().runAllTests(args);
+
+ //Exit explicitly otherwise dalvikvm won't quit
+ System.exit(0);
+ }
+}
diff --git a/platform/android/src/test/main.jni.cpp b/platform/android/src/test/main.jni.cpp
new file mode 100644
index 0000000000..f79d7671cb
--- /dev/null
+++ b/platform/android/src/test/main.jni.cpp
@@ -0,0 +1,101 @@
+#include "../jni.hpp"
+
+#include <android/log.h>
+#include <jni/jni.hpp>
+#include <jni/jni.hpp>
+
+#include <mbgl/util/logging.hpp>
+#include <mbgl/test.hpp>
+
+#include <vector>
+
+#pragma clang diagnostic ignored "-Wunused-parameter"
+
+#define MAKE_NATIVE_METHOD(name, sig) jni::MakeNativeMethod<decltype(name), name>( #name, sig )
+
+namespace {
+
+// Main class (entry point for tests from dalvikvm)
+struct Main {
+ static constexpr auto Name() {
+ return "Main";
+ }
+
+ /**
+ * JNI Bound to Main#runAllTests()
+ */
+ static void runAllTests(jni::JNIEnv& env, jni::Object<Main>, jni::Array<jni::String> args) {
+ mbgl::Log::Warning(mbgl::Event::JNI, "Starting tests");
+
+ // We need to create a copy of the argv data since Java-internals are stored in UTF-16.
+ std::vector<std::string> data;
+ // Add a fake first argument to align indices. Google Test expects the first argument to
+ // start at index 1; index 0 is the name of the executable.
+ data.push_back("main.jar");
+ const int argc = args.Length(env);
+ for (auto i = 0; i < argc; i++) {
+ data.emplace_back(jni::Make<std::string>(env, args.Get(env, i)));
+ }
+
+ // Create an array of char pointers that point back to the data array.
+ std::vector<const char*> argv;
+ for (const auto& arg : data) {
+ argv.push_back(arg.data());
+ }
+ mbgl::runTests(argv.size(), const_cast<char**>(argv.data()));
+ }
+};
+
+} // namespace
+
+// JNI Bindings to stub the android.util.Log implementation
+
+static jboolean isLoggable(JNIEnv* env, jni::jobject* clazz, jni::jstring* tag, jint level) {
+ return true;
+}
+
+static jint println_native(JNIEnv* env, jni::jobject* clazz, jint bufID, jint priority, jni::jstring* jtag, jni::jstring* jmessage) {
+ if (jtag == nullptr || jmessage == nullptr) {
+ return false;
+ }
+
+ std::string tag = jni::Make<std::string>(*env, jni::String(jtag));
+ std::string message = jni::Make<std::string>(*env, jni::String(jmessage));
+
+ return __android_log_print(priority, tag.c_str(), "%s", message.c_str());
+}
+
+static jint logger_entry_max_payload_native(JNIEnv* env, jni::jobject* clazz) {
+ return static_cast<jint>(4068);
+}
+
+
+// Main entry point
+
+extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+ // Load the main library jni bindings
+ mbgl::Log::Info(mbgl::Event::JNI, "Registering main JNI Methods");
+ mbgl::android::registerNatives(vm);
+
+ // Load the test library jni bindings
+ mbgl::Log::Info(mbgl::Event::JNI, "Registering test JNI Methods");
+
+ jni::JNIEnv& env = jni::GetEnv(*vm, jni::jni_version_1_6);
+
+ jni::RegisterNatives(env, jni::Class<Main>::Find(env),
+ jni::MakeNativeMethod<decltype(Main::runAllTests), &Main::runAllTests>("runAllTests"));
+
+ // Bindings for system classes
+ struct Log { static constexpr auto Name() { return "android/util/Log"; } };
+ try {
+ jni::RegisterNatives(env, jni::Class<Log>::Find(env),
+ MAKE_NATIVE_METHOD(isLoggable, "(Ljava/lang/String;I)Z"),
+ MAKE_NATIVE_METHOD(logger_entry_max_payload_native, "()I"),
+ MAKE_NATIVE_METHOD(println_native, "(IILjava/lang/String;Ljava/lang/String;)I")
+ );
+ } catch (jni::PendingJavaException ex) {
+ env.ThrowNew(jni::JavaErrorClass(env), "Could not register Log mocks");
+ }
+
+ return JNI_VERSION_1_6;
+}
diff --git a/platform/android/src/thread.cpp b/platform/android/src/thread.cpp
index 77f9815866..c708dfdceb 100644
--- a/platform/android/src/thread.cpp
+++ b/platform/android/src/thread.cpp
@@ -1,5 +1,5 @@
-#include <mbgl/platform/log.hpp>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/logging.hpp>
+#include <mbgl/util/platform.hpp>
#include <sys/prctl.h>
#include <sys/resource.h>
diff --git a/platform/android/tests/README.md b/platform/android/tests/README.md
index 69e75b693b..8c4d29e831 100644
--- a/platform/android/tests/README.md
+++ b/platform/android/tests/README.md
@@ -3,7 +3,8 @@
## Testing
We currently support the following types of testing on the Mapbox Android SDK:
- - [Unit tests](https://github.com/mapbox/mapbox-gl-native/blob/3447-Add-test-documentation/platform/android/tests/docs/UNIT_TESTS.md) using [JUnit](http://developer.android.com/tools/testing-support-library/index.html#AndroidJUnitRunner)
- - [UI tests](https://github.com/mapbox/mapbox-gl-native/blob/3447-Add-test-documentation/platform/android/tests/docs/UI_TESTS.md) using [Espresso](http://developer.android.com/tools/testing-support-library/index.html#Espresso)
- - [Exerciser](https://github.com/mapbox/mapbox-gl-native/blob/3447-Add-test-documentation/platform/android/tests/docs/EXERCISER_TESTS.md) tests using [Monkey](http://developer.android.com/tools/help/monkey.html) or [Build-in Fuzz test](http://docs.aws.amazon.com/devicefarm/latest/developerguide/test-types-built-in-fuzz.html)
- - [Performance tests](https://github.com/mapbox/mapbox-gl-native/blob/3447-Add-test-documentation/platform/android/tests/docs/PERFORMANCE_TESTS.md) using [Systrace](https://codelabs.developers.google.com/codelabs/android-perf-testing/index.html?index=..%2F..%2Fbabbq-2015&viewga=UA-68632703-1#0)
+ - [Unit tests](docs/UNIT_TESTS.md) using [JUnit](http://developer.android.com/tools/testing-support-library/index.html#AndroidJUnitRunner)
+ - [UI tests](docs/UI_TESTS.md) using [Espresso](http://developer.android.com/tools/testing-support-library/index.html#Espresso)
+ - [Exerciser](docs/EXERCISER_TESTS.md) tests using [Monkey](http://developer.android.com/tools/help/monkey.html) or [Build-in Fuzz test](http://docs.aws.amazon.com/devicefarm/latest/developerguide/test-types-built-in-fuzz.html)
+ - [Performance tests](docs/PERFORMANCE_TESTS.md) using [Systrace](https://codelabs.developers.google.com/codelabs/android-perf-testing/index.html?index=..%2F..%2Fbabbq-2015&viewga=UA-68632703-1#0)
+ - [Core tests](docs/CORE_TESTS.md) using [Google Test](https://github.com/google/googletest) to run the unit tests written for the core rendering component of Mapbox GL \ No newline at end of file
diff --git a/platform/android/tests/docs/ACTIVITY_SANITY_TEST.md b/platform/android/tests/docs/ACTIVITY_SANITY_TEST.md
index 14e4335111..7422599c38 100644
--- a/platform/android/tests/docs/ACTIVITY_SANITY_TEST.md
+++ b/platform/android/tests/docs/ACTIVITY_SANITY_TEST.md
@@ -6,7 +6,7 @@ This type of test checks if an Activity doesn't crash at start up. For this proj
The generation is done by executing:
-> make android-generate-test
+> make test-code-android
This command underneath executes the following js file found in:
diff --git a/platform/android/tests/docs/CORE_TESTS.md b/platform/android/tests/docs/CORE_TESTS.md
new file mode 100644
index 0000000000..b9cd7bcc76
--- /dev/null
+++ b/platform/android/tests/docs/CORE_TESTS.md
@@ -0,0 +1,21 @@
+# Core Tests
+
+Core tests run the [unit tests](../../../../test) written for the core rendering component of Mapbox GL.
+
+## Running the tests
+
+To run the tests, connect a device to your computer, or launch a virtual device. Then run
+
+```
+$ make run-android-core-test-XXX
+```
+
+with `XXX` being the architecture of the device (one of `arm-v5`, `arm-v7`, `arm-v8`, `x86`, `x86-64`, or `mips`). This command first builds the library, creates a test program, zips up the assets required for the unit tests, deploys it on the device, runs the test and unpacks the results again on your computer.
+
+You can also run individual tests by specifying the name like this:
+
+```
+$ make run-android-core-test-XXX-TileCover.*
+```
+
+Everything after the last dash is passed as the [`--gtest_filter` argument](https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#running-a-subset-of-the-tests) to the Google Test binary.
diff --git a/include/mbgl/platform/darwin/reachability.h b/platform/darwin/mbgl/storage/reachability.h
index 78e302eafc..78e302eafc 100644
--- a/include/mbgl/platform/darwin/reachability.h
+++ b/platform/darwin/mbgl/storage/reachability.h
diff --git a/platform/darwin/src/reachability.m b/platform/darwin/mbgl/storage/reachability.m
index 8abcf5ae6d..aa6746a2a9 100644
--- a/platform/darwin/src/reachability.m
+++ b/platform/darwin/mbgl/storage/reachability.m
@@ -25,7 +25,7 @@
POSSIBILITY OF SUCH DAMAGE.
*/
-#import <mbgl/platform/darwin/reachability.h>
+#import <mbgl/storage/reachability.h>
#import <sys/socket.h>
#import <netinet/in.h>
diff --git a/platform/darwin/resources/zh-Hans.lproj/Foundation.strings b/platform/darwin/resources/zh-Hans.lproj/Foundation.strings
new file mode 100644
index 0000000000..7dec6184e5
--- /dev/null
+++ b/platform/darwin/resources/zh-Hans.lproj/Foundation.strings
@@ -0,0 +1,291 @@
+/* Clock position format, long: {hours} o’clock */
+"CLOCK_FMT_LONG" = "%@点";
+
+/* Clock position format, medium: {hours} o’clock */
+"CLOCK_FMT_MEDIUM" = "%@点";
+
+/* Clock position format, short: {hours}:00 */
+"CLOCK_FMT_SHORT" = "%@:00";
+
+/* East, long */
+"COMPASS_E_LONG" = "东";
+
+/* East, short */
+"COMPASS_E_SHORT" = "东";
+
+/* East by north, long */
+"COMPASS_EbN_LONG" = "东微北";
+
+/* East by north, short */
+"COMPASS_EbN_SHORT" = "东微北";
+
+/* East by south, long */
+"COMPASS_EbS_LONG" = "东微南";
+
+/* East by south, short */
+"COMPASS_EbS_SHORT" = "东微南";
+
+/* East-northeast, long */
+"COMPASS_ENE_LONG" = "东北偏东";
+
+/* East-northeast, short */
+"COMPASS_ENE_SHORT" = "东北偏东";
+
+/* East-southeast, long */
+"COMPASS_ESE_LONG" = "东南偏东";
+
+/* East-southeast, short */
+"COMPASS_ESE_SHORT" = "东南偏东";
+
+/* North, long */
+"COMPASS_N_LONG" = "北";
+
+/* North, short */
+"COMPASS_N_SHORT" = "北";
+
+/* North by east, long */
+"COMPASS_NbE_LONG" = "北微东";
+
+/* North by east, short */
+"COMPASS_NbE_SHORT" = "北微东";
+
+/* North by west, long */
+"COMPASS_NbW_LONG" = "北微西";
+
+/* North by west, short */
+"COMPASS_NbW_SHORT" = "北微西";
+
+/* Northeast, long */
+"COMPASS_NE_LONG" = "东北";
+
+/* Northeast, short */
+"COMPASS_NE_SHORT" = "东北";
+
+/* Northeast by east, long */
+"COMPASS_NEbE_LONG" = "东北微东";
+
+/* Northeast by east, short */
+"COMPASS_NEbE_SHORT" = "东北微东";
+
+/* Northeast by north, long */
+"COMPASS_NEbN_LONG" = "东北微北";
+
+/* Northeast by north, short */
+"COMPASS_NEbN_SHORT" = "东北微北";
+
+/* North-northeast, long */
+"COMPASS_NNE_LONG" = "东北偏北";
+
+/* North-northeast, short */
+"COMPASS_NNE_SHORT" = "东北偏北";
+
+/* North-northwest, long */
+"COMPASS_NNW_LONG" = "西北偏北";
+
+/* North-northwest, short */
+"COMPASS_NNW_SHORT" = "西北偏北";
+
+/* Northwest, long */
+"COMPASS_NW_LONG" = "西北";
+
+/* Northwest, short */
+"COMPASS_NW_SHORT" = "西北";
+
+/* Northwest by north, long */
+"COMPASS_NWbN_LONG" = "西北微北";
+
+/* Northwest by north, short */
+"COMPASS_NWbN_SHORT" = "西北微北";
+
+/* Northwest by west, long */
+"COMPASS_NWbW_LONG" = "西北微西";
+
+/* Northwest by west, short */
+"COMPASS_NWbW_SHORT" = "西北微西";
+
+/* South, long */
+"COMPASS_S_LONG" = "南";
+
+/* South, short */
+"COMPASS_S_SHORT" = "南";
+
+/* South by east, long */
+"COMPASS_SbE_LONG" = "南微东";
+
+/* South by east, short */
+"COMPASS_SbE_SHORT" = "南微东";
+
+/* South by west, long */
+"COMPASS_SbW_LONG" = "南微西";
+
+/* South by west, short */
+"COMPASS_SbW_SHORT" = "南微西";
+
+/* Southeast, long */
+"COMPASS_SE_LONG" = "东南";
+
+/* Southeast, short */
+"COMPASS_SE_SHORT" = "东南";
+
+/* Southeast by east, long */
+"COMPASS_SEbE_LONG" = "东南微东";
+
+/* Southeast by east, short */
+"COMPASS_SEbE_SHORT" = "东南微东";
+
+/* Southeast by south, long */
+"COMPASS_SEbS_LONG" = "东南微南";
+
+/* Southeast by south, short */
+"COMPASS_SEbS_SHORT" = "东南微南";
+
+/* South-southeast, long */
+"COMPASS_SSE_LONG" = "东南偏南";
+
+/* South-southeast, short */
+"COMPASS_SSE_SHORT" = "东南偏南";
+
+/* South-southwest, long */
+"COMPASS_SSW_LONG" = "西南偏南";
+
+/* South-southwest, short */
+"COMPASS_SSW_SHORT" = "西南偏南";
+
+/* Southwest, long */
+"COMPASS_SW_LONG" = "西南";
+
+/* Southwest, short */
+"COMPASS_SW_SHORT" = "西南";
+
+/* Southwest by south, long */
+"COMPASS_SWbS_LONG" = "西南偏南";
+
+/* Southwest by south, short */
+"COMPASS_SWbS_SHORT" = "西南偏南";
+
+/* Southwest by west, long */
+"COMPASS_SWbW_LONG" = "西南偏西";
+
+/* Southwest by west, short */
+"COMPASS_SWbW_SHORT" = "西南偏西";
+
+/* West, long */
+"COMPASS_W_LONG" = "西";
+
+/* West, short */
+"COMPASS_W_SHORT" = "西";
+
+/* West by north, long */
+"COMPASS_WbN_LONG" = "西微北";
+
+/* West by north, short */
+"COMPASS_WbN_SHORT" = "西微北";
+
+/* West by south, long */
+"COMPASS_WbS_LONG" = "西微南";
+
+/* West by south, short */
+"COMPASS_WbS_SHORT" = "西微南";
+
+/* West-northwest, long */
+"COMPASS_WNW_LONG" = "西北偏西";
+
+/* West-northwest, short */
+"COMPASS_WNW_SHORT" = "西北偏西";
+
+/* West-southwest, long */
+"COMPASS_WSW_LONG" = "西南偏西";
+
+/* West-southwest, short */
+"COMPASS_WSW_SHORT" = "西南偏西";
+
+/* Degrees format, long */
+"COORD_DEG_LONG" = "%d度";
+
+/* Degrees format, medium: {degrees} */
+"COORD_DEG_MEDIUM" = "%d°";
+
+/* Degrees format, short: {degrees} */
+"COORD_DEG_SHORT" = "%d°";
+
+/* Coordinate format, long: {degrees}{minutes} */
+"COORD_DM_LONG" = "%1$@度%2$@分";
+
+/* Coordinate format, medium: {degrees}{minutes} */
+"COORD_DM_MEDIUM" = "%1$@度%2$@";
+
+/* Coordinate format, short: {degrees}{minutes} */
+"COORD_DM_SHORT" = "%1$@%度2$@";
+
+/* Coordinate format, long: {degrees}{minutes}{seconds} */
+"COORD_DMS_LONG" = "%1$@度%2$@分%3$@秒";
+
+/* Coordinate format, medium: {degrees}{minutes}{seconds} */
+"COORD_DMS_MEDIUM" = "%1$@度%2$@分%3$@秒";
+
+/* Coordinate format, short: {degrees}{minutes}{seconds} */
+"COORD_DMS_SHORT" = "%1$@%度2$@分%3$@秒";
+
+/* East longitude format, long: {longitude} */
+"COORD_E_LONG" = "东经%@";
+
+/* East longitude format, medium: {longitude} */
+"COORD_E_MEDIUM" = "东经%@";
+
+/* East longitude format, short: {longitude} */
+"COORD_E_SHORT" = "%@E";
+
+/* Coordinate pair format, long: {latitude}, {longitude} */
+"COORD_FMT_LONG" = "%1$@,%2$@";
+
+/* Coordinate pair format, medium: {latitude}, {longitude} */
+"COORD_FMT_MEDIUM" = "%1$@,%2$@";
+
+/* Coordinate pair format, short: {latitude}, {longitude} */
+"COORD_FMT_SHORT" = "%1$@,%2$@";
+
+/* Minutes format, long */
+"COORD_MIN_LONG" = "%d分";
+
+/* Minutes format, medium: {minutes} */
+"COORD_MIN_MEDIUM" = "%d′";
+
+/* Minutes format, short: {minutes} */
+"COORD_MIN_SHORT" = "%d′";
+
+/* North latitude format, long: {latitude} */
+"COORD_N_LONG" = "北纬%@";
+
+/* North latitude format, medium: {latitude} */
+"COORD_N_MEDIUM" = "北纬%@";
+
+/* North latitude format, short: {latitude} */
+"COORD_N_SHORT" = "%@N";
+
+/* South latitude format, long: {latitude} */
+"COORD_S_LONG" = "南纬%@";
+
+/* South latitude format, medium: {latitude} */
+"COORD_S_MEDIUM" = "南纬%@";
+
+/* South latitude format, short: {latitude} */
+"COORD_S_SHORT" = "%@S";
+
+/* Seconds format, long */
+"COORD_SEC_LONG" = "%d秒";
+
+/* Seconds format, medium: {seconds} */
+"COORD_SEC_MEDIUM" = "%d″";
+
+/* Seconds format, short: {seconds} */
+"COORD_SEC_SHORT" = "%d″";
+
+/* West longitude format, long: {longitude} */
+"COORD_W_LONG" = "西经%@";
+
+/* West longitude format, medium: {longitude} */
+"COORD_W_MEDIUM" = "西经%@";
+
+/* West longitude format, short: {longitude} */
+"COORD_W_SHORT" = "%@W";
+
diff --git a/platform/darwin/scripts/check-public-symbols.js b/platform/darwin/scripts/check-public-symbols.js
new file mode 100755
index 0000000000..4dde5d677b
--- /dev/null
+++ b/platform/darwin/scripts/check-public-symbols.js
@@ -0,0 +1,83 @@
+#!/usr/bin/env node
+
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const execFileSync = require('child_process').execFileSync;
+const _ = require('lodash');
+
+const keyword = /\bMGL_EXPORT\b/;
+
+let scanned = [];
+
+function hasMissingSymbols(os) {
+ let missing = false;
+ let sdk = os === 'iOS' ? 'iphonesimulator' : 'macosx';
+ let sysroot = execFileSync('xcrun', ['--show-sdk-path', '--sdk', sdk]).toString().trim();
+ let umbrellaPath = `platform/${os.toLowerCase()}/src/Mapbox.h`;
+ let docArgs = ['doc', '--objc', umbrellaPath, '--',
+ '-x', 'objective-c', '-I', 'platform/darwin/src/', '-isysroot', sysroot];
+ let docStr = execFileSync('sourcekitten', docArgs).toString().trim();
+ let docJson = JSON.parse(docStr);
+ _.forEach(docJson, function (result) {
+ _.forEach(result, function (structure, path) {
+ // Prevent multiple scans of the same file.
+ if (scanned.indexOf(path) >= 0) return;
+ scanned.push(path);
+
+ const src = fs.readFileSync(path, 'utf8').split('\n');
+ _.forEach(structure['key.substructure'], function (substructure) {
+ switch (substructure['key.kind']) {
+ case 'sourcekitten.source.lang.objc.decl.class':
+ if (!(keyword.test(src[substructure['key.doc.line'] - 1]) || keyword.test(src[substructure['key.doc.line'] - 2]))) {
+ console.warn(`- missing symbol export for class ${substructure['key.name']} in ${path}:${substructure['key.doc.line']}:${substructure['key.doc.column']}`);
+ missing = true;
+ }
+ break;
+ case 'sourcekitten.source.lang.objc.decl.constant':
+ if (!keyword.test(src[substructure['key.doc.line'] - 1])) {
+ console.warn(`- missing symbol export for constant ${substructure['key.name']} in ${path}:${substructure['key.doc.line']}:${substructure['key.doc.column']}`);
+ missing = true;
+ }
+ break;
+ }
+ });
+ });
+ });
+
+ return missing;
+}
+
+function ensureSourceKittenIsInstalled() {
+ try {
+ execFileSync('which', ['sourcekitten']);
+ } catch (e) {
+ console.log(`Installing SourceKitten via Homebrew…`);
+ execFileSync('brew', ['install', 'sourcekitten']);
+ }
+}
+
+if (process.argv.length < 3) {
+ console.warn(`Usage: ${path.relative(process.cwd(), process.argv[1])} [macOS|iOS] ...`);
+ process.exit(1);
+}
+
+ensureSourceKittenIsInstalled();
+
+let missing = false;
+for (var i = 2; i < process.argv.length; i++) {
+ let os = process.argv[i];
+ if (os == 'iOS' || os == 'macOS') {
+ missing |= hasMissingSymbols(os);
+ } else {
+ console.warn(`Argument must be one of iOS or macOS`);
+ process.exit(1);
+ }
+}
+
+if (missing) {
+ process.exit(1);
+} else {
+ console.warn(`All symbols are correctly exported.`);
+}
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js
index 0266e25890..3998246580 100644
--- a/platform/darwin/scripts/generate-style-code.js
+++ b/platform/darwin/scripts/generate-style-code.js
@@ -4,11 +4,20 @@ const fs = require('fs');
const ejs = require('ejs');
const _ = require('lodash');
const colorParser = require('csscolorparser');
+
+require('../../../scripts/style-code');
+
const cocoaConventions = require('./style-spec-cocoa-conventions-v8.json');
-let spec = _.merge(require('mapbox-gl-style-spec').latest, require('./style-spec-overrides-v8.json'));
const prefix = 'MGL';
const suffix = 'StyleLayer';
+let spec = _.merge(require('mapbox-gl-style-spec').latest, require('./style-spec-overrides-v8.json'));
+
+///
+// Temporarily IGNORE layers that are in the spec yet still not supported in mbgl core
+///
+delete spec.layer.type.values['fill-extrusion'];
+
// Rename properties and keep `original` for use with setters and getters
_.forOwn(cocoaConventions, function (properties, kind) {
_.forOwn(properties, function (newName, oldName) {
@@ -148,7 +157,7 @@ global.mbglTestValue = function (property, layerType) {
return `mbgl::style::${type}Type::${value}`;
}
case 'color':
- return '{ .r = 1, .g = 0, .b = 0, .a = 1 }';
+ return '{ 1, 0, 0, 1 }';
case 'array':
switch (arrayType(property)) {
case 'dasharray':
@@ -558,7 +567,7 @@ for (var layer of layers) {
if (!_.isEmpty(renamedProperties)) {
renamedPropertiesByLayerType[layer.type] = renamedProperties;
}
-
+
fs.writeFileSync(`platform/darwin/src/${prefix}${camelize(layer.type)}${suffix}.h`, duplicatePlatformDecls(layerH(layer)));
fs.writeFileSync(`platform/darwin/src/${prefix}${camelize(layer.type)}${suffix}.mm`, layerM(layer));
fs.writeFileSync(`platform/darwin/test/${prefix}${camelize(layer.type)}${suffix}Tests.mm`, testLayers(layer));
diff --git a/platform/darwin/src/MGLAccountManager.h b/platform/darwin/src/MGLAccountManager.h
index fe602aa210..c1aebd879c 100644
--- a/platform/darwin/src/MGLAccountManager.h
+++ b/platform/darwin/src/MGLAccountManager.h
@@ -1,11 +1,14 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
The MGLAccountManager object provides a global way to set a Mapbox API access
token.
*/
+MGL_EXPORT
@interface MGLAccountManager : NSObject
#pragma mark Authorizing Access
diff --git a/platform/darwin/src/MGLAttributionInfo.h b/platform/darwin/src/MGLAttributionInfo.h
index 3c9df47912..c4e037059e 100644
--- a/platform/darwin/src/MGLAttributionInfo.h
+++ b/platform/darwin/src/MGLAttributionInfo.h
@@ -2,6 +2,7 @@
#import <CoreGraphics/CoreGraphics.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLTypes.h"
NS_ASSUME_NONNULL_BEGIN
@@ -10,6 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
Information about an attribution statement, usually a copyright or trademark
statement, associated with a map content source.
*/
+MGL_EXPORT
@interface MGLAttributionInfo : NSObject
/**
diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.h b/platform/darwin/src/MGLBackgroundStyleLayer.h
index ed797c9f0a..06d7c9ee08 100644
--- a/platform/darwin/src/MGLBackgroundStyleLayer.h
+++ b/platform/darwin/src/MGLBackgroundStyleLayer.h
@@ -1,6 +1,7 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLStyleLayer.h"
@@ -20,6 +21,7 @@ NS_ASSUME_NONNULL_BEGIN
If the background style layer is transparent or omitted from the style, any
portion of the map view that does not show another style layer is transparent.
*/
+MGL_EXPORT
@interface MGLBackgroundStyleLayer : MGLStyleLayer
- (instancetype)initWithIdentifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER;
diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.mm b/platform/darwin/src/MGLBackgroundStyleLayer.mm
index f6a00de941..caf8ca9681 100644
--- a/platform/darwin/src/MGLBackgroundStyleLayer.mm
+++ b/platform/darwin/src/MGLBackgroundStyleLayer.mm
@@ -1,5 +1,5 @@
// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -8,6 +8,7 @@
#import "MGLStyleValue_Private.h"
#import "MGLBackgroundStyleLayer.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/background_layer.hpp>
@interface MGLBackgroundStyleLayer ()
diff --git a/platform/darwin/src/MGLCircleStyleLayer.h b/platform/darwin/src/MGLCircleStyleLayer.h
index 1117077d59..8d8c4588e7 100644
--- a/platform/darwin/src/MGLCircleStyleLayer.h
+++ b/platform/darwin/src/MGLCircleStyleLayer.h
@@ -1,6 +1,7 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLVectorStyleLayer.h"
@@ -75,6 +76,7 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
mapView.style?.addLayer(layer)
```
*/
+MGL_EXPORT
@interface MGLCircleStyleLayer : MGLVectorStyleLayer
#pragma mark - Accessing the Paint Attributes
@@ -146,6 +148,47 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
#if TARGET_OS_IPHONE
/**
+ The stroke color of the circle.
+
+ The default value of this property is an `MGLStyleValue` object containing
+ `UIColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *circleStrokeColor;
+#else
+/**
+ The stroke color of the circle.
+
+ The default value of this property is an `MGLStyleValue` object containing
+ `NSColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *circleStrokeColor;
+#endif
+
+/**
+ The opacity of the circle's stroke.
+
+ The default value of this property is an `MGLStyleValue` object containing an
+ `NSNumber` object containing the float `1`. Set this property to `nil` to reset
+ it to the default value.
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleStrokeOpacity;
+
+/**
+ The width of the circle's stroke. Strokes are placed outside of the
+ "circle-radius".
+
+ This property is measured in points.
+
+ The default value of this property is an `MGLStyleValue` object containing an
+ `NSNumber` object containing the float `0`. Set this property to `nil` to reset
+ it to the default value.
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleStrokeWidth;
+
+#if TARGET_OS_IPHONE
+/**
The geometry's offset.
This property is measured in points.
diff --git a/platform/darwin/src/MGLCircleStyleLayer.mm b/platform/darwin/src/MGLCircleStyleLayer.mm
index 0aff74ffa6..adc5ed8dd3 100644
--- a/platform/darwin/src/MGLCircleStyleLayer.mm
+++ b/platform/darwin/src/MGLCircleStyleLayer.mm
@@ -1,5 +1,5 @@
// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -8,7 +8,9 @@
#import "MGLStyleValue_Private.h"
#import "MGLCircleStyleLayer.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
+
namespace mbgl {
MBGL_DEFINE_ENUM(MGLCircleScaleAlignment, {
@@ -208,6 +210,48 @@ namespace mbgl {
return self.circleScaleAlignment;
}
+- (void)setCircleStrokeColor:(MGLStyleValue<MGLColor *> *)circleStrokeColor {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(circleStrokeColor);
+ self.rawLayer->setCircleStrokeColor(mbglValue);
+}
+
+- (MGLStyleValue<MGLColor *> *)circleStrokeColor {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getCircleStrokeColor() ?: self.rawLayer->getDefaultCircleStrokeColor();
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
+}
+
+- (void)setCircleStrokeOpacity:(MGLStyleValue<NSNumber *> *)circleStrokeOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleStrokeOpacity);
+ self.rawLayer->setCircleStrokeOpacity(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)circleStrokeOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getCircleStrokeOpacity() ?: self.rawLayer->getDefaultCircleStrokeOpacity();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+}
+
+- (void)setCircleStrokeWidth:(MGLStyleValue<NSNumber *> *)circleStrokeWidth {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleStrokeWidth);
+ self.rawLayer->setCircleStrokeWidth(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)circleStrokeWidth {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getCircleStrokeWidth() ?: self.rawLayer->getDefaultCircleStrokeWidth();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+}
+
- (void)setCircleTranslation:(MGLStyleValue<NSValue *> *)circleTranslation {
MGLAssertStyleLayerIsValid();
diff --git a/platform/darwin/src/MGLClockDirectionFormatter.h b/platform/darwin/src/MGLClockDirectionFormatter.h
index ea427aa7b1..a428f51c63 100644
--- a/platform/darwin/src/MGLClockDirectionFormatter.h
+++ b/platform/darwin/src/MGLClockDirectionFormatter.h
@@ -1,6 +1,8 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
@@ -14,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
irrespective of the user’s orientation, use `MGLCompassDirectionFormatter`
instead.
*/
+MGL_EXPORT
@interface MGLClockDirectionFormatter : NSFormatter
/**
diff --git a/platform/darwin/src/MGLCompassDirectionFormatter.h b/platform/darwin/src/MGLCompassDirectionFormatter.h
index fde26ba42a..714e1cc035 100644
--- a/platform/darwin/src/MGLCompassDirectionFormatter.h
+++ b/platform/darwin/src/MGLCompassDirectionFormatter.h
@@ -1,6 +1,8 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
@@ -12,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
irrespective of the user’s current location. To format a direction relative to
the user’s current location, use `MGLClockDirectionFormatter` instead.
*/
+MGL_EXPORT
@interface MGLCompassDirectionFormatter : NSFormatter
/**
diff --git a/platform/darwin/src/MGLCoordinateFormatter.h b/platform/darwin/src/MGLCoordinateFormatter.h
index 909c1e8935..c42c196d5a 100644
--- a/platform/darwin/src/MGLCoordinateFormatter.h
+++ b/platform/darwin/src/MGLCoordinateFormatter.h
@@ -1,6 +1,8 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
@@ -8,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN
geographic coordinate pairs. Use this class to create localized coordinate
strings when displaying location information to users.
*/
+MGL_EXPORT
@interface MGLCoordinateFormatter : NSFormatter
/**
diff --git a/platform/darwin/src/MGLFeature.h b/platform/darwin/src/MGLFeature.h
index 30abcb1934..82dbb450cf 100644
--- a/platform/darwin/src/MGLFeature.h
+++ b/platform/darwin/src/MGLFeature.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLPolyline.h"
#import "MGLPolygon.h"
#import "MGLPointAnnotation.h"
@@ -148,6 +149,7 @@ NS_ASSUME_NONNULL_BEGIN
An `MGLPointFeature` object associates a point shape with an optional
identifier and attributes.
*/
+MGL_EXPORT
@interface MGLPointFeature : MGLPointAnnotation <MGLFeature>
@end
@@ -159,6 +161,7 @@ NS_ASSUME_NONNULL_BEGIN
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.4">LineString</a>
feature in GeoJSON.
*/
+MGL_EXPORT
@interface MGLPolylineFeature : MGLPolyline <MGLFeature>
@end
@@ -166,6 +169,7 @@ NS_ASSUME_NONNULL_BEGIN
An `MGLPolygonFeature` object associates a polygon shape with an optional
identifier and attributes.
*/
+MGL_EXPORT
@interface MGLPolygonFeature : MGLPolygon <MGLFeature>
@end
@@ -177,6 +181,7 @@ NS_ASSUME_NONNULL_BEGIN
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.3">MultiPoint</a>
feature in GeoJSON.
*/
+MGL_EXPORT
@interface MGLPointCollectionFeature : MGLPointCollection <MGLFeature>
@end
@@ -191,6 +196,7 @@ NS_ASSUME_NONNULL_BEGIN
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.5">MultiLineString</a>
feature in GeoJSON.
*/
+MGL_EXPORT
@interface MGLMultiPolylineFeature : MGLMultiPolyline <MGLFeature>
@end
@@ -198,6 +204,7 @@ NS_ASSUME_NONNULL_BEGIN
An `MGLMultiPolygonFeature` object associates a multipolygon shape with an
optional identifier and attributes.
*/
+MGL_EXPORT
@interface MGLMultiPolygonFeature : MGLMultiPolygon <MGLFeature>
@end
@@ -209,6 +216,7 @@ NS_ASSUME_NONNULL_BEGIN
<a href="https://tools.ietf.org/html/rfc7946#section-3.3">feature collection</a>
in GeoJSON.
*/
+MGL_EXPORT
@interface MGLShapeCollectionFeature : MGLShapeCollection <MGLFeature>
@property (nonatomic, copy, readonly) NS_ARRAY_OF(MGLShape<MGLFeature> *) *shapes;
diff --git a/platform/darwin/src/MGLFeature_Private.h b/platform/darwin/src/MGLFeature_Private.h
index 3277a94d5b..6751b3196a 100644
--- a/platform/darwin/src/MGLFeature_Private.h
+++ b/platform/darwin/src/MGLFeature_Private.h
@@ -1,3 +1,4 @@
+#import "MGLFoundation.h"
#import "MGLFeature.h"
#import "MGLShape.h"
@@ -11,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN
Returns an array of `MGLFeature` objects converted from the given vector of
vector tile features.
*/
+MGL_EXPORT
NS_ARRAY_OF(MGLShape <MGLFeature> *) *MGLFeaturesFromMBGLFeatures(const std::vector<mbgl::Feature> &features);
/**
diff --git a/platform/darwin/src/MGLFillStyleLayer.h b/platform/darwin/src/MGLFillStyleLayer.h
index d05b21eb51..2ab02acf5a 100644
--- a/platform/darwin/src/MGLFillStyleLayer.h
+++ b/platform/darwin/src/MGLFillStyleLayer.h
@@ -1,6 +1,7 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLVectorStyleLayer.h"
@@ -48,6 +49,7 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
mapView.style?.addLayer(layer)
```
*/
+MGL_EXPORT
@interface MGLFillStyleLayer : MGLVectorStyleLayer
#pragma mark - Accessing the Paint Attributes
diff --git a/platform/darwin/src/MGLFillStyleLayer.mm b/platform/darwin/src/MGLFillStyleLayer.mm
index ec736d8825..63a482ac2e 100644
--- a/platform/darwin/src/MGLFillStyleLayer.mm
+++ b/platform/darwin/src/MGLFillStyleLayer.mm
@@ -1,5 +1,5 @@
// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -8,7 +8,9 @@
#import "MGLStyleValue_Private.h"
#import "MGLFillStyleLayer.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
+
namespace mbgl {
MBGL_DEFINE_ENUM(MGLFillTranslationAnchor, {
diff --git a/platform/darwin/src/MGLForegroundStyleLayer.h b/platform/darwin/src/MGLForegroundStyleLayer.h
index 642dde4992..474e1f6307 100644
--- a/platform/darwin/src/MGLForegroundStyleLayer.h
+++ b/platform/darwin/src/MGLForegroundStyleLayer.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLStyleLayer.h"
NS_ASSUME_NONNULL_BEGIN
@@ -14,6 +15,7 @@ NS_ASSUME_NONNULL_BEGIN
subclasses of this class. Instead, create instances of `MGLRasterStyleLayer`
and the concrete subclasses of `MGLVectorStyleLayer`.
*/
+MGL_EXPORT
@interface MGLForegroundStyleLayer : MGLStyleLayer
#pragma mark Initializing a Style Layer
diff --git a/platform/darwin/src/MGLFoundation.h b/platform/darwin/src/MGLFoundation.h
new file mode 100644
index 0000000000..3400c63979
--- /dev/null
+++ b/platform/darwin/src/MGLFoundation.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#import <Foundation/Foundation.h>
+
+#define MGL_EXPORT __attribute__((visibility ("default")))
diff --git a/platform/darwin/src/MGLGeometry.h b/platform/darwin/src/MGLGeometry.h
index 8e36b86d96..408bdb2632 100644
--- a/platform/darwin/src/MGLGeometry.h
+++ b/platform/darwin/src/MGLGeometry.h
@@ -2,6 +2,8 @@
#import <CoreLocation/CoreLocation.h>
#import <CoreGraphics/CGBase.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/** Defines the area spanned by an `MGLCoordinateBounds`. */
@@ -33,7 +35,7 @@ NS_INLINE BOOL MGLCoordinateSpanEqualToCoordinateSpan(MGLCoordinateSpan span1, M
}
/** An area of zero width and zero height. */
-extern const MGLCoordinateSpan MGLCoordinateSpanZero;
+extern MGL_EXPORT const MGLCoordinateSpan MGLCoordinateSpanZero;
/** A rectangular area as measured on a two-dimensional map projection. */
typedef struct MGLCoordinateBounds {
diff --git a/platform/darwin/src/MGLGeometry.mm b/platform/darwin/src/MGLGeometry.mm
index 70f00afd2f..36e096dd03 100644
--- a/platform/darwin/src/MGLGeometry.mm
+++ b/platform/darwin/src/MGLGeometry.mm
@@ -1,12 +1,14 @@
#import "MGLGeometry_Private.h"
+#import "MGLFoundation.h"
+
#import <mbgl/util/projection.hpp>
/** Vertical field of view, measured in degrees, for determining the altitude
of the viewpoint.
- TransformState::getProjMatrix() assumes a vertical field of view of
- 2 arctan ⅓ rad ≈ 36.9°, but MapKit uses a vertical field of view of 30°.
+ TransformState::getProjMatrix() has a variable vertical field of view that
+ defaults to 2 arctan ⅓ rad ≈ 36.9° but MapKit uses a vertical field of view of 30°.
flyTo() assumes a field of view of 2 arctan ½ rad. */
const CLLocationDegrees MGLAngularFieldOfView = 30;
@@ -30,6 +32,7 @@ CGRect MGLExtendRect(CGRect rect, CGPoint point) {
return rect;
}
+MGL_EXPORT
CLLocationDistance MGLAltitudeForZoomLevel(double zoomLevel, CGFloat pitch, CLLocationDegrees latitude, CGSize size) {
CLLocationDistance metersPerPixel = mbgl::Projection::getMetersPerPixelAtLatitude(latitude, zoomLevel);
CLLocationDistance metersTall = metersPerPixel * size.height;
@@ -37,6 +40,7 @@ CLLocationDistance MGLAltitudeForZoomLevel(double zoomLevel, CGFloat pitch, CLLo
return altitude * std::sin(M_PI_2 - MGLRadiansFromDegrees(pitch)) / std::sin(M_PI_2);
}
+MGL_EXPORT
double MGLZoomLevelForAltitude(CLLocationDistance altitude, CGFloat pitch, CLLocationDegrees latitude, CGSize size) {
CLLocationDistance eyeAltitude = altitude / std::sin(M_PI_2 - MGLRadiansFromDegrees(pitch)) * std::sin(M_PI_2);
CLLocationDistance metersTall = eyeAltitude * 2 * std::tan(MGLRadiansFromDegrees(MGLAngularFieldOfView) / 2.);
diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h
index 9b37a97460..98f2778291 100644
--- a/platform/darwin/src/MGLLineStyleLayer.h
+++ b/platform/darwin/src/MGLLineStyleLayer.h
@@ -1,6 +1,7 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLVectorStyleLayer.h"
@@ -103,6 +104,7 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
mapView.style?.addLayer(layer)
```
*/
+MGL_EXPORT
@interface MGLLineStyleLayer : MGLVectorStyleLayer
#pragma mark - Accessing the Layout Attributes
diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm
index f6884fad15..13408d426c 100644
--- a/platform/darwin/src/MGLLineStyleLayer.mm
+++ b/platform/darwin/src/MGLLineStyleLayer.mm
@@ -1,5 +1,5 @@
// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -8,7 +8,9 @@
#import "MGLStyleValue_Private.h"
#import "MGLLineStyleLayer.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/line_layer.hpp>
+
namespace mbgl {
MBGL_DEFINE_ENUM(MGLLineCap, {
diff --git a/platform/darwin/src/MGLMapCamera.h b/platform/darwin/src/MGLMapCamera.h
index f6bff36280..3d492656af 100644
--- a/platform/darwin/src/MGLMapCamera.h
+++ b/platform/darwin/src/MGLMapCamera.h
@@ -2,12 +2,15 @@
#import <CoreGraphics/CoreGraphics.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
An `MGLMapCamera` object represents a viewpoint from which the user observes
some point on an `MGLMapView`.
*/
+MGL_EXPORT
@interface MGLMapCamera : NSObject <NSSecureCoding, NSCopying>
/** Coordinate at the center of the map view. */
diff --git a/platform/darwin/src/MGLMultiPoint.h b/platform/darwin/src/MGLMultiPoint.h
index f083a5bec4..31ab5744a3 100644
--- a/platform/darwin/src/MGLMultiPoint.h
+++ b/platform/darwin/src/MGLMultiPoint.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLShape.h"
NS_ASSUME_NONNULL_BEGIN
@@ -17,6 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
Do not confuse `MGLMultiPoint` with `MGLPointCollection`, which represents a
collection of related but disconnected points.
*/
+MGL_EXPORT
@interface MGLMultiPoint : MGLShape
/**
diff --git a/platform/darwin/src/MGLOfflinePack.h b/platform/darwin/src/MGLOfflinePack.h
index a741833105..8436434e68 100644
--- a/platform/darwin/src/MGLOfflinePack.h
+++ b/platform/darwin/src/MGLOfflinePack.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLOfflineRegion.h"
NS_ASSUME_NONNULL_BEGIN
@@ -100,6 +101,7 @@ typedef struct MGLOfflinePackProgress {
`+[MGLOfflineStorage addPackForRegion:withContext:completionHandler:]` method.
A pack created using `-[MGLOfflinePack init]` is immediately invalid.
*/
+MGL_EXPORT
@interface MGLOfflinePack : NSObject
/**
diff --git a/platform/darwin/src/MGLOfflineStorage.h b/platform/darwin/src/MGLOfflineStorage.h
index 6e60f26e77..9125c5341e 100644
--- a/platform/darwin/src/MGLOfflineStorage.h
+++ b/platform/darwin/src/MGLOfflineStorage.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLTypes.h"
NS_ASSUME_NONNULL_BEGIN
@@ -25,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
alternatively observe KVO change notifications to the pack’s `progress` key
path.
*/
-extern const NSNotificationName MGLOfflinePackProgressChangedNotification;
+extern MGL_EXPORT const NSNotificationName MGLOfflinePackProgressChangedNotification;
/**
Posted by the shared `MGLOfflineStorage` object whenever an `MGLOfflinePack`
@@ -38,7 +39,7 @@ extern const NSNotificationName MGLOfflinePackProgressChangedNotification;
`userInfo` dictionary contains the error object in the
`MGLOfflinePackErrorUserInfoKey` key.
*/
-extern const NSNotificationName MGLOfflinePackErrorNotification;
+extern MGL_EXPORT const NSNotificationName MGLOfflinePackErrorNotification;
/**
Posted by the shared `MGLOfflineStorage` object when the maximum number of
@@ -53,7 +54,7 @@ extern const NSNotificationName MGLOfflinePackErrorNotification;
calling the `-[MGLOfflineStorage removePack:withCompletionHandler:]` method.
Contact your Mapbox sales representative to have the limit raised.
*/
-extern const NSNotificationName MGLOfflinePackMaximumMapboxTilesReachedNotification;
+extern MGL_EXPORT const NSNotificationName MGLOfflinePackMaximumMapboxTilesReachedNotification;
/**
A key in the `userInfo` property of a notification posted by `MGLOfflinePack`.
@@ -66,9 +67,9 @@ typedef NSString *MGLOfflinePackUserInfoKey NS_EXTENSIBLE_STRING_ENUM;
`MGLOfflinePackProgressChangedNotification` notification. Call `-integerValue`
on the object to receive the `MGLOfflinePackState`-typed state.
*/
-extern const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyState;
+extern MGL_EXPORT const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyState;
-extern NSString * const MGLOfflinePackStateUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyState")));
+extern MGL_EXPORT NSString * const MGLOfflinePackStateUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyState")));
/**
The key for an `NSValue` object that indicates an offline pack’s current
@@ -77,9 +78,9 @@ extern NSString * const MGLOfflinePackStateUserInfoKey __attribute__((deprecated
`-MGLOfflinePackProgressValue` on the object to receive the
`MGLOfflinePackProgress`-typed progress.
*/
-extern const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyProgress;
+extern MGL_EXPORT const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyProgress;
-extern NSString * const MGLOfflinePackProgressUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyProgress")));
+extern MGL_EXPORT NSString * const MGLOfflinePackProgressUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyProgress")));
/**
The key for an `NSError` object that is encountered in the course of
@@ -87,9 +88,9 @@ extern NSString * const MGLOfflinePackProgressUserInfoKey __attribute__((depreca
an `MGLOfflinePackErrorNotification` notification. The error’s domain is
`MGLErrorDomain`. See `MGLErrorCode` for possible error codes.
*/
-extern const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyError;
+extern MGL_EXPORT const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyError;
-extern NSString * const MGLOfflinePackErrorUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyError")));
+extern MGL_EXPORT NSString * const MGLOfflinePackErrorUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyError")));
/**
The key for an `NSNumber` object that indicates the maximum number of
@@ -99,9 +100,9 @@ extern NSString * const MGLOfflinePackErrorUserInfoKey __attribute__((deprecated
`-unsignedLongLongValue` on the object to receive the `uint64_t`-typed tile
limit.
*/
-extern const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyMaximumCount;
+extern MGL_EXPORT const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyMaximumCount;
-extern NSString * const MGLOfflinePackMaximumCountUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyMaximumCount")));
+extern MGL_EXPORT NSString * const MGLOfflinePackMaximumCountUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyMaximumCount")));
/**
A block to be called once an offline pack has been completely created and
@@ -136,6 +137,7 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error
fact that offline resources are stored in a database. The shared object
maintains a canonical collection of offline packs in its `packs` property.
*/
+MGL_EXPORT
@interface MGLOfflineStorage : NSObject
/**
diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.h b/platform/darwin/src/MGLOpenGLStyleLayer.h
index f395484436..de4fc92b17 100644
--- a/platform/darwin/src/MGLOpenGLStyleLayer.h
+++ b/platform/darwin/src/MGLOpenGLStyleLayer.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLStyleLayer.h"
@@ -14,8 +15,10 @@ typedef struct MGLStyleLayerDrawingContext {
double zoomLevel;
CLLocationDirection direction;
CGFloat pitch;
+ CGFloat fieldOfView;
} MGLStyleLayerDrawingContext;
+MGL_EXPORT
@interface MGLOpenGLStyleLayer : MGLStyleLayer
@property (nonatomic, weak, readonly) MGLMapView *mapView;
diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.mm b/platform/darwin/src/MGLOpenGLStyleLayer.mm
index 12986f64c1..5d81eb85ea 100644
--- a/platform/darwin/src/MGLOpenGLStyleLayer.mm
+++ b/platform/darwin/src/MGLOpenGLStyleLayer.mm
@@ -4,6 +4,7 @@
#import "MGLStyle_Private.h"
#import "MGLStyleLayer_Private.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/math/wrap.hpp>
@@ -34,6 +35,7 @@ void MGLDrawCustomStyleLayer(void *context, const mbgl::style::CustomLayerRender
.zoomLevel = params.zoom,
.direction = mbgl::util::wrap(params.bearing, 0., 360.),
.pitch = static_cast<CGFloat>(params.pitch),
+ .fieldOfView = static_cast<CGFloat>(params.fieldOfView),
};
[layer drawInMapView:layer.mapView withContext:drawingContext];
}
diff --git a/platform/darwin/src/MGLPointAnnotation.h b/platform/darwin/src/MGLPointAnnotation.h
index 969f8c91e7..aeac43bd39 100644
--- a/platform/darwin/src/MGLPointAnnotation.h
+++ b/platform/darwin/src/MGLPointAnnotation.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLShape.h"
NS_ASSUME_NONNULL_BEGIN
@@ -33,6 +34,7 @@ NS_ASSUME_NONNULL_BEGIN
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.2">Point</a> geometry
in GeoJSON.
*/
+MGL_EXPORT
@interface MGLPointAnnotation : MGLShape
/**
diff --git a/platform/darwin/src/MGLPointCollection.h b/platform/darwin/src/MGLPointCollection.h
index 9e14161aed..c7054c6bbf 100644
--- a/platform/darwin/src/MGLPointCollection.h
+++ b/platform/darwin/src/MGLPointCollection.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLOverlay.h"
#import "MGLShape.h"
@@ -26,6 +27,7 @@
geometry in GeoJSON. Do not confuse `MGLPointCollection` with `MGLMultiPoint`,
the abstract superclass of `MGLPolyline` and `MGLPolygon`.
*/
+MGL_EXPORT
@interface MGLPointCollection : MGLShape <MGLOverlay>
/**
diff --git a/platform/darwin/src/MGLPolygon.h b/platform/darwin/src/MGLPolygon.h
index 674c006095..560741a150 100644
--- a/platform/darwin/src/MGLPolygon.h
+++ b/platform/darwin/src/MGLPolygon.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLMultiPoint.h"
#import "MGLOverlay.h"
@@ -43,6 +44,7 @@ NS_ASSUME_NONNULL_BEGIN
To make the polygon straddle the antimeridian, specify some longitudes less
than −180 degrees or greater than 180 degrees.
*/
+MGL_EXPORT
@interface MGLPolygon : MGLMultiPoint <MGLOverlay>
/**
@@ -100,6 +102,7 @@ NS_ASSUME_NONNULL_BEGIN
`-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]`. However, you can
add the `polygons` array’s items as overlays individually.
*/
+MGL_EXPORT
@interface MGLMultiPolygon : MGLShape <MGLOverlay>
/**
diff --git a/platform/darwin/src/MGLPolyline.h b/platform/darwin/src/MGLPolyline.h
index 429ba9cddc..ca1f8e36cc 100644
--- a/platform/darwin/src/MGLPolyline.h
+++ b/platform/darwin/src/MGLPolyline.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLMultiPoint.h"
#import "MGLOverlay.h"
@@ -39,6 +40,7 @@ NS_ASSUME_NONNULL_BEGIN
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.4">LineString</a>
geometry in GeoJSON.
*/
+MGL_EXPORT
@interface MGLPolyline : MGLMultiPoint <MGLOverlay>
/**
@@ -73,6 +75,7 @@ NS_ASSUME_NONNULL_BEGIN
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.5">MultiLineString</a>
geometry in GeoJSON.
*/
+MGL_EXPORT
@interface MGLMultiPolyline : MGLShape <MGLOverlay>
/**
diff --git a/platform/darwin/src/MGLRasterSource.h b/platform/darwin/src/MGLRasterSource.h
index c2807c8d2e..ac5be60105 100644
--- a/platform/darwin/src/MGLRasterSource.h
+++ b/platform/darwin/src/MGLRasterSource.h
@@ -1,7 +1,8 @@
-#import "MGLTileSource.h"
-
#import <CoreGraphics/CoreGraphics.h>
+#import "MGLFoundation.h"
+#import "MGLTileSource.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
@@ -18,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
This option is only applicable to `MGLRasterSource` objects; it is ignored when
initializing `MGLVectorSource` objects.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionTileSize;
+extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionTileSize;
/**
`MGLRasterSource` is a map content source that supplies raster image tiles to
@@ -50,6 +51,7 @@ extern const MGLTileSourceOption MGLTileSourceOptionTileSize;
mapView.style?.addSource(source)
```
*/
+MGL_EXPORT
@interface MGLRasterSource : MGLTileSource
#pragma mark Initializing a Source
diff --git a/platform/darwin/src/MGLRasterSource.mm b/platform/darwin/src/MGLRasterSource.mm
index b52b4e3eed..fd36413fe0 100644
--- a/platform/darwin/src/MGLRasterSource.mm
+++ b/platform/darwin/src/MGLRasterSource.mm
@@ -5,7 +5,7 @@
#import "MGLTileSource_Private.h"
#import "NSURL+MGLAdditions.h"
-#include <mbgl/mbgl.hpp>
+#include <mbgl/map/map.hpp>
#include <mbgl/style/sources/raster_source.hpp>
const MGLTileSourceOption MGLTileSourceOptionTileSize = @"MGLTileSourceOptionTileSize";
diff --git a/platform/darwin/src/MGLRasterStyleLayer.h b/platform/darwin/src/MGLRasterStyleLayer.h
index 736e8ee2f5..cd57a74f6a 100644
--- a/platform/darwin/src/MGLRasterStyleLayer.h
+++ b/platform/darwin/src/MGLRasterStyleLayer.h
@@ -1,6 +1,7 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLForegroundStyleLayer.h"
@@ -32,6 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
mapView.style?.addLayer(layer)
```
*/
+MGL_EXPORT
@interface MGLRasterStyleLayer : MGLForegroundStyleLayer
#pragma mark - Accessing the Paint Attributes
diff --git a/platform/darwin/src/MGLRasterStyleLayer.mm b/platform/darwin/src/MGLRasterStyleLayer.mm
index 22e182df61..87afb8da9d 100644
--- a/platform/darwin/src/MGLRasterStyleLayer.mm
+++ b/platform/darwin/src/MGLRasterStyleLayer.mm
@@ -1,5 +1,5 @@
// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -8,6 +8,7 @@
#import "MGLStyleValue_Private.h"
#import "MGLRasterStyleLayer.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/raster_layer.hpp>
@interface MGLRasterStyleLayer ()
diff --git a/platform/darwin/src/MGLShape.h b/platform/darwin/src/MGLShape.h
index 8dc1b4f1cf..d1c150d02e 100644
--- a/platform/darwin/src/MGLShape.h
+++ b/platform/darwin/src/MGLShape.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLAnnotation.h"
NS_ASSUME_NONNULL_BEGIN
@@ -27,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
you can add some kinds of shapes directly to a map view as annotations or
overlays.
*/
+MGL_EXPORT
@interface MGLShape : NSObject <MGLAnnotation, NSSecureCoding>
#pragma mark Creating a Shape
diff --git a/platform/darwin/src/MGLShapeCollection.h b/platform/darwin/src/MGLShapeCollection.h
index 01aece824f..5d2ce588c9 100644
--- a/platform/darwin/src/MGLShapeCollection.h
+++ b/platform/darwin/src/MGLShapeCollection.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLShape.h"
#import "MGLTypes.h"
@@ -32,6 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.8">GeometryCollection</a>
geometry in GeoJSON.
*/
+MGL_EXPORT
@interface MGLShapeCollection : MGLShape
/**
diff --git a/platform/darwin/src/MGLShapeSource.h b/platform/darwin/src/MGLShapeSource.h
index a44db69475..34806c548d 100644
--- a/platform/darwin/src/MGLShapeSource.h
+++ b/platform/darwin/src/MGLShapeSource.h
@@ -1,5 +1,6 @@
#import "MGLSource.h"
+#import "MGLFoundation.h"
#import "MGLTypes.h"
#import "MGLShape.h"
@@ -21,14 +22,14 @@ typedef NSString *MGLShapeSourceOption NS_STRING_ENUM;
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-cluster"><code>cluster</code></a>
source property in the Mapbox Style Specification.
*/
-extern const MGLShapeSourceOption MGLShapeSourceOptionClustered;
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClustered;
/**
An `NSNumber` object containing an integer; specifies the radius of each
cluster if clustering is enabled. A value of 512 produces a radius equal to
the width of a tile. The default value is 50.
*/
-extern const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius;
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius;
/**
An `NSNumber` object containing an integer; specifies the maximum zoom level at
@@ -40,7 +41,7 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius;
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-clusterMaxZoom"><code>clusterMaxZoom</code></a>
source property in the Mapbox Style Specification.
*/
-extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering;
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering;
/**
An `NSNumber` object containing an integer; specifies the maximum zoom level at
@@ -51,7 +52,7 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForCluster
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-maxzoom"><code>maxzoom</code></a>
source property in the Mapbox Style Specification.
*/
-extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel;
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel;
/**
An `NSNumber` object containing an integer; specifies the size of the tile
@@ -63,7 +64,7 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel;
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-buffer"><code>buffer</code></a>
source property in the Mapbox Style Specification.
*/
-extern const MGLShapeSourceOption MGLShapeSourceOptionBuffer;
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionBuffer;
/**
An `NSNumber` object containing a double; specifies the Douglas-Peucker
@@ -74,7 +75,7 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionBuffer;
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-tolerance"><code>tolerance</code></a>
source property in the Mapbox Style Specification.
*/
-extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
/**
`MGLShapeSource` is a map content source that supplies vector shapes to be
@@ -107,6 +108,7 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
mapView.style?.addSource(source)
```
*/
+MGL_EXPORT
@interface MGLShapeSource : MGLSource
#pragma mark Initializing a Source
diff --git a/platform/darwin/src/MGLShapeSource.mm b/platform/darwin/src/MGLShapeSource.mm
index 50322f300c..245b7f2de2 100644
--- a/platform/darwin/src/MGLShapeSource.mm
+++ b/platform/darwin/src/MGLShapeSource.mm
@@ -7,7 +7,7 @@
#import "NSURL+MGLAdditions.h"
-#include <mbgl/mbgl.hpp>
+#include <mbgl/map/map.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
const MGLShapeSourceOption MGLShapeSourceOptionClustered = @"MGLShapeSourceOptionClustered";
diff --git a/platform/darwin/src/MGLShapeSource_Private.h b/platform/darwin/src/MGLShapeSource_Private.h
index 584a5a4b30..c14f4fbb59 100644
--- a/platform/darwin/src/MGLShapeSource_Private.h
+++ b/platform/darwin/src/MGLShapeSource_Private.h
@@ -1,5 +1,5 @@
+#import "MGLFoundation.h"
#import "MGLShapeSource.h"
-#import "MGLShapeSource_Private.h"
NS_ASSUME_NONNULL_BEGIN
@@ -16,6 +16,7 @@ namespace mbgl {
@end
+MGL_EXPORT
mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options);
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLSource.h b/platform/darwin/src/MGLSource.h
index 03bb5fcba2..7b3242e3ae 100644
--- a/platform/darwin/src/MGLSource.h
+++ b/platform/darwin/src/MGLSource.h
@@ -1,5 +1,7 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
@@ -18,6 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
subclasses of this class. Instead, create instances of `MGLShapeSource` and the
concrete subclasses of `MGLTileSource`, `MGLVectorSource` and `MGLRasterSource`.
*/
+MGL_EXPORT
@interface MGLSource : NSObject
#pragma mark Initializing a Source
diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h
index fcb464a303..9bd35142c2 100644
--- a/platform/darwin/src/MGLStyle.h
+++ b/platform/darwin/src/MGLStyle.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLStyleLayer.h"
#import "MGLTypes.h"
@@ -27,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
the constant itself. Such details may change significantly from version to
version.
*/
-static const NSInteger MGLStyleDefaultVersion = 9;
+static MGL_EXPORT const NSInteger MGLStyleDefaultVersion = 9;
/**
The proxy object for the current map style.
@@ -45,6 +46,7 @@ static const NSInteger MGLStyleDefaultVersion = 9;
`-[MGLMapViewDelegate mapViewDidFinishLoadingMap:]` methods as indicators
that it's safe to modify the map's style.
*/
+MGL_EXPORT
@interface MGLStyle : NSObject
#pragma mark Accessing Default Styles
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index fcfa762972..7e96c08ccc 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -24,6 +24,7 @@
#import "MGLAttributionInfo_Private.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/util/default_styles.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
@@ -36,7 +37,6 @@
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/sources/vector_source.hpp>
#include <mbgl/style/sources/raster_source.hpp>
-#include <mbgl/mbgl.hpp>
#if TARGET_OS_IPHONE
#import "UIImage+MGLAdditions.h"
@@ -71,7 +71,11 @@ static_assert(mbgl::util::default_styles::currentVersion == MGLStyleDefaultVersi
} \
\
+ (NSURL *)name##StyleURL##WithVersion:(NSInteger)version { \
- return [NSURL URLWithString:[@"mapbox://styles/mapbox/" #fileName "-v" stringByAppendingFormat:@"%li", (long)version]]; \
+ if (mbgl::util::default_styles::currentVersion == version) { \
+ return [NSURL URLWithString:@(mbgl::util::default_styles::name.url)]; \
+ } else { \
+ return [NSURL URLWithString:[@"mapbox://styles/mapbox/" #fileName "-v" stringByAppendingFormat:@"%li", (long)version]]; \
+ } \
}
MGL_DEFINE_STYLE(streets, streets)
diff --git a/platform/darwin/src/MGLStyleLayer.h b/platform/darwin/src/MGLStyleLayer.h
index 4032be9297..ac40545398 100644
--- a/platform/darwin/src/MGLStyleLayer.h
+++ b/platform/darwin/src/MGLStyleLayer.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLTypes.h"
NS_ASSUME_NONNULL_BEGIN
@@ -18,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
`MGLBackgroundStyleLayer` and the concrete subclasses of
`MGLForegroundStyleLayer`.
*/
+MGL_EXPORT
@interface MGLStyleLayer : NSObject
#pragma mark Initializing a Style Layer
diff --git a/platform/darwin/src/MGLStyleLayer.h.ejs b/platform/darwin/src/MGLStyleLayer.h.ejs
index a10512dbcb..8ffed66b54 100644
--- a/platform/darwin/src/MGLStyleLayer.h.ejs
+++ b/platform/darwin/src/MGLStyleLayer.h.ejs
@@ -8,6 +8,7 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGL<%-
(type === 'background' ? '' :
@@ -75,6 +76,7 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) {
```
*/
<% } -%>
+MGL_EXPORT
@interface MGL<%- camelize(type) %>StyleLayer : MGL<%-
(type === 'background' ? '' :
(type === 'raster' ? 'Foreground' :
diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs
index ec8f8599b3..9445c3cf21 100644
--- a/platform/darwin/src/MGLStyleLayer.mm.ejs
+++ b/platform/darwin/src/MGLStyleLayer.mm.ejs
@@ -5,7 +5,7 @@
const enumProperties = locals.enumProperties;
-%>
// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -14,8 +14,10 @@
#import "MGLStyleValue_Private.h"
#import "MGL<%- camelize(type) %>StyleLayer.h"
-#include <mbgl/style/layers/<%- type %>_layer.hpp>
+#include <mbgl/map/map.hpp>
+#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp>
<% if (enumProperties) { -%>
+
namespace mbgl {
<% if (layoutProperties.length) { -%>
diff --git a/platform/darwin/src/MGLStyleLayer_Private.h b/platform/darwin/src/MGLStyleLayer_Private.h
index c5e3e76549..8f1cdfb4a1 100644
--- a/platform/darwin/src/MGLStyleLayer_Private.h
+++ b/platform/darwin/src/MGLStyleLayer_Private.h
@@ -3,7 +3,6 @@
#import "MGLStyleLayer.h"
#import "MGLStyleValue_Private.h"
-#include <mbgl/mbgl.hpp>
#include <mbgl/style/layer.hpp>
NS_ASSUME_NONNULL_BEGIN
diff --git a/platform/darwin/src/MGLStyleValue.h b/platform/darwin/src/MGLStyleValue.h
index eec7ed9781..5b6528f6fd 100644
--- a/platform/darwin/src/MGLStyleValue.h
+++ b/platform/darwin/src/MGLStyleValue.h
@@ -1,6 +1,8 @@
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
@@ -25,6 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
<li><code>NSArray</code></li>
</ul>
*/
+MGL_EXPORT
@interface MGLStyleValue<T> : NSObject
#pragma mark Creating a Style Value
@@ -68,6 +71,7 @@ NS_ASSUME_NONNULL_BEGIN
The `MGLStyleConstantValue` class takes a generic parameter `T` that indicates
the Foundation class being wrapped by this class.
*/
+MGL_EXPORT
@interface MGLStyleConstantValue<T> : MGLStyleValue<T>
#pragma mark Creating a Style Constant Value
@@ -111,6 +115,7 @@ NS_ASSUME_NONNULL_BEGIN
The `MGLStyleFunction` class takes a generic parameter `T` that indicates the
Foundation class being wrapped by this class.
*/
+MGL_EXPORT
@interface MGLStyleFunction<T> : MGLStyleValue<T>
#pragma mark Creating a Style Function
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h
index c693978ab6..23ddd59d0d 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.h
+++ b/platform/darwin/src/MGLSymbolStyleLayer.h
@@ -1,6 +1,7 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLVectorStyleLayer.h"
@@ -276,6 +277,7 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
mapView.style?.addLayer(layer)
```
*/
+MGL_EXPORT
@interface MGLSymbolStyleLayer : MGLVectorStyleLayer
#pragma mark - Accessing the Layout Attributes
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm
index c7ba9d7dc5..493a8c5b6f 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.mm
+++ b/platform/darwin/src/MGLSymbolStyleLayer.mm
@@ -1,5 +1,5 @@
// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -8,7 +8,9 @@
#import "MGLStyleValue_Private.h"
#import "MGLSymbolStyleLayer.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
+
namespace mbgl {
MBGL_DEFINE_ENUM(MGLIconRotationAlignment, {
diff --git a/platform/darwin/src/MGLTilePyramidOfflineRegion.h b/platform/darwin/src/MGLTilePyramidOfflineRegion.h
index 4e9f394e74..4c6237702d 100644
--- a/platform/darwin/src/MGLTilePyramidOfflineRegion.h
+++ b/platform/darwin/src/MGLTilePyramidOfflineRegion.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLOfflineRegion.h"
#import "MGLGeometry.h"
@@ -9,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN
An offline region defined by a style URL, geographic coordinate bounds, and
range of zoom levels.
*/
+MGL_EXPORT
@interface MGLTilePyramidOfflineRegion : NSObject <MGLOfflineRegion, NSSecureCoding, NSCopying>
/**
diff --git a/platform/darwin/src/MGLTileSource.h b/platform/darwin/src/MGLTileSource.h
index db5bc73338..99d23f4add 100644
--- a/platform/darwin/src/MGLTileSource.h
+++ b/platform/darwin/src/MGLTileSource.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLSource.h"
#import "MGLTypes.h"
@@ -24,7 +25,7 @@ typedef NSString *MGLTileSourceOption NS_STRING_ENUM;
<a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">TileJSON</a>
specification.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionMinimumZoomLevel;
+extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionMinimumZoomLevel;
/**
An `NSNumber` object containing an unsigned integer that specifies the maximum
@@ -38,7 +39,7 @@ extern const MGLTileSourceOption MGLTileSourceOptionMinimumZoomLevel;
<a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">TileJSON</a>
specification.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel;
+extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel;
#if TARGET_OS_IPHONE
/**
@@ -54,7 +55,7 @@ extern const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel;
<a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">TileJSON</a>
specification.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString;
+extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString;
/**
An array of `MGLAttributionInfo` objects defining the buttons to be displayed
@@ -63,7 +64,7 @@ extern const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString;
By default, no attribution statements are displayed.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionAttributionInfos;
+extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionAttributionInfos;
#else
/**
An HTML string defining the buttons to be displayed in the map view’s
@@ -77,7 +78,7 @@ extern const MGLTileSourceOption MGLTileSourceOptionAttributionInfos;
<a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">TileJSON</a>
specification.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString;
+extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString;
/**
An array of `MGLAttributionInfo` objects defining the buttons to be displayed
@@ -86,7 +87,7 @@ extern const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString;
By default, no attribution statements are displayed.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionAttributionInfos;
+extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionAttributionInfos;
#endif
/**
@@ -100,7 +101,7 @@ extern const MGLTileSourceOption MGLTileSourceOptionAttributionInfos;
<a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">TileJSON</a>
specification.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionTileCoordinateSystem;
+extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionTileCoordinateSystem;
/**
Tile coordinate systems that determine how tile coordinates in tile URLs are
@@ -139,6 +140,7 @@ typedef NS_ENUM(NSUInteger, MGLTileCoordinateSystem) {
subclasses of this class. Instead, create instances of `MGLRasterSource` and
`MGLVectorSource`.
*/
+MGL_EXPORT
@interface MGLTileSource : MGLSource
#pragma mark Initializing a Source
diff --git a/platform/darwin/src/MGLTileSource_Private.h b/platform/darwin/src/MGLTileSource_Private.h
index ca80e3d960..8da69274f2 100644
--- a/platform/darwin/src/MGLTileSource_Private.h
+++ b/platform/darwin/src/MGLTileSource_Private.h
@@ -1,7 +1,8 @@
-#import "MGLTileSource.h"
-
#import <CoreGraphics/CoreGraphics.h>
+#import "MGLFoundation.h"
+#import "MGLTileSource.h"
+
NS_ASSUME_NONNULL_BEGIN
namespace mbgl {
@@ -31,6 +32,7 @@ namespace mbgl {
@end
+MGL_EXPORT
mbgl::Tileset MGLTileSetFromTileURLTemplates(NS_ARRAY_OF(NSString *) *tileURLTemplates, NS_DICTIONARY_OF(MGLTileSourceOption, id) * _Nullable options);
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLTypes.h b/platform/darwin/src/MGLTypes.h
index a6b7254b58..8cd2cacaa6 100644
--- a/platform/darwin/src/MGLTypes.h
+++ b/platform/darwin/src/MGLTypes.h
@@ -1,5 +1,7 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
+
#pragma once
#if TARGET_OS_IPHONE
@@ -28,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN
#endif
/** Indicates an error occurred in the Mapbox SDK. */
-extern NSErrorDomain const MGLErrorDomain;
+extern MGL_EXPORT NSErrorDomain const MGLErrorDomain;
/** Error constants for the Mapbox SDK. */
typedef NS_ENUM(NSInteger, MGLErrorCode) {
diff --git a/platform/darwin/src/MGLVectorSource.h b/platform/darwin/src/MGLVectorSource.h
index 5032ca3863..bfa52f5b49 100644
--- a/platform/darwin/src/MGLVectorSource.h
+++ b/platform/darwin/src/MGLVectorSource.h
@@ -1,3 +1,4 @@
+#import "MGLFoundation.h"
#import "MGLTileSource.h"
NS_ASSUME_NONNULL_BEGIN
@@ -38,6 +39,7 @@ NS_ASSUME_NONNULL_BEGIN
mapView.style?.addSource(source)
```
*/
+MGL_EXPORT
@interface MGLVectorSource : MGLTileSource
- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL NS_DESIGNATED_INITIALIZER;
diff --git a/platform/darwin/src/MGLVectorSource.mm b/platform/darwin/src/MGLVectorSource.mm
index c95ff63bbf..8fda528546 100644
--- a/platform/darwin/src/MGLVectorSource.mm
+++ b/platform/darwin/src/MGLVectorSource.mm
@@ -5,7 +5,7 @@
#import "MGLTileSource_Private.h"
#import "NSURL+MGLAdditions.h"
-#include <mbgl/mbgl.hpp>
+#include <mbgl/map/map.hpp>
#include <mbgl/style/sources/vector_source.hpp>
@interface MGLVectorSource ()
diff --git a/platform/darwin/src/MGLVectorStyleLayer.h b/platform/darwin/src/MGLVectorStyleLayer.h
index 360b86c517..ca09c11716 100644
--- a/platform/darwin/src/MGLVectorStyleLayer.h
+++ b/platform/darwin/src/MGLVectorStyleLayer.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLForegroundStyleLayer.h"
NS_ASSUME_NONNULL_BEGIN
@@ -13,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
subclasses: `MGLCircleStyleLayer`, `MGLFillStyleLayer`, `MGLLineStyleLayer`,
and `MGLSymbolStyleLayer`.
*/
+MGL_EXPORT
@interface MGLVectorStyleLayer : MGLForegroundStyleLayer
#pragma mark Refining a Style Layer’s Content
diff --git a/platform/darwin/src/NSDate+MGLAdditions.h b/platform/darwin/src/NSDate+MGLAdditions.h
index a116ef32de..918aae233f 100644
--- a/platform/darwin/src/NSDate+MGLAdditions.h
+++ b/platform/darwin/src/NSDate+MGLAdditions.h
@@ -1,6 +1,5 @@
#import <Foundation/Foundation.h>
-#include <mbgl/mbgl.hpp>
#include <mbgl/util/chrono.hpp>
@interface NSDate (MGLAdditions)
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm
index f11a1919cf..b095091b17 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.mm
+++ b/platform/darwin/src/NSExpression+MGLAdditions.mm
@@ -69,9 +69,6 @@
if (mbglValue.is<std::string>()) {
return mbglValue.get<std::string>();
}
- if (mbglValue.is<bool>()) {
- return mbglValue.get<bool>();
- }
if (mbglValue.is<double>()) {
return mbglValue.get<double>();
}
diff --git a/platform/darwin/src/headless_backend_cgl.cpp b/platform/darwin/src/headless_backend_cgl.cpp
index 4ca567f55c..7069738fb1 100644
--- a/platform/darwin/src/headless_backend_cgl.cpp
+++ b/platform/darwin/src/headless_backend_cgl.cpp
@@ -1,6 +1,7 @@
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/headless_display.hpp>
+#include <OpenGL/OpenGL.h>
#include <CoreFoundation/CoreFoundation.h>
#include <string>
@@ -8,6 +9,33 @@
namespace mbgl {
+struct CGLImpl : public HeadlessBackend::Impl {
+ CGLImpl(CGLContextObj glContext_) : glContext(glContext_) {
+ }
+
+ ~CGLImpl() {
+ CGLDestroyContext(glContext);
+ }
+
+ void activateContext() final {
+ CGLError error = CGLSetCurrentContext(glContext);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Switching OpenGL context failed:") +
+ CGLErrorString(error) + "\n");
+ }
+ }
+
+ void deactivateContext() final {
+ CGLError error = CGLSetCurrentContext(nullptr);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Removing OpenGL context failed:") +
+ CGLErrorString(error) + "\n");
+ }
+ }
+
+ CGLContextObj glContext = nullptr;
+};
+
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
if (!framework) {
@@ -21,8 +49,18 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) {
return reinterpret_cast<gl::glProc>(symbol);
}
+bool HeadlessBackend::hasDisplay() {
+ if (!display) {
+ display.reset(new HeadlessDisplay);
+ }
+ return bool(display);
+}
+
void HeadlessBackend::createContext() {
- CGLError error = CGLCreateContext(display->pixelFormat, nullptr, &glContext);
+ assert(!hasContext());
+
+ CGLContextObj glContext = nullptr;
+ CGLError error = CGLCreateContext(display->attribute<CGLPixelFormatObj>(), nullptr, &glContext);
if (error != kCGLNoError) {
throw std::runtime_error(std::string("Error creating GL context object:") +
CGLErrorString(error) + "\n");
@@ -33,26 +71,8 @@ void HeadlessBackend::createContext() {
throw std::runtime_error(std::string("Error enabling OpenGL multithreading:") +
CGLErrorString(error) + "\n");
}
-}
-
-void HeadlessBackend::destroyContext() {
- CGLDestroyContext(glContext);
-}
-
-void HeadlessBackend::activateContext() {
- CGLError error = CGLSetCurrentContext(glContext);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Switching OpenGL context failed:") +
- CGLErrorString(error) + "\n");
- }
-}
-void HeadlessBackend::deactivateContext() {
- CGLError error = CGLSetCurrentContext(nullptr);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Removing OpenGL context failed:") +
- CGLErrorString(error) + "\n");
- }
+ impl.reset(new CGLImpl(glContext));
}
} // namespace mbgl
diff --git a/platform/darwin/src/headless_backend_eagl.mm b/platform/darwin/src/headless_backend_eagl.mm
index 0a1ae706b8..bd4a202ec5 100644
--- a/platform/darwin/src/headless_backend_eagl.mm
+++ b/platform/darwin/src/headless_backend_eagl.mm
@@ -1,4 +1,4 @@
-#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/gl/headless_backend.hpp>
#include <mbgl/gl/extension.hpp>
@@ -8,6 +8,27 @@
namespace mbgl {
+struct EAGLImpl : public HeadlessBackend::Impl {
+ EAGLImpl(EAGLContext* glContext_) : glContext(glContext_) {
+ [reinterpret_cast<EAGLContext*>(glContext) retain];
+ reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES;
+ }
+
+ ~EAGLImpl() {
+ [glContext release];
+ }
+
+ void activateContext() {
+ [EAGLContext setCurrentContext:glContext];
+ }
+
+ void deactivateContext() {
+ [EAGLContext setCurrentContext:nil];
+ }
+
+ EAGLContext* glContext = nullptr;
+};
+
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
if (!framework) {
@@ -21,26 +42,17 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) {
return reinterpret_cast<gl::glProc>(symbol);
}
+bool HeadlessBackend::hasDisplay() {
+ return true;
+}
+
void HeadlessBackend::createContext() {
- glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+ EAGLContext* glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
if (glContext == nil) {
throw std::runtime_error("Error creating GL context object");
}
- [reinterpret_cast<EAGLContext*>(glContext) retain];
- reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES;
-}
-
-void HeadlessBackend::destroyContext() {
- [reinterpret_cast<EAGLContext*>(glContext) release];
- glContext = nil;
-}
-
-void HeadlessBackend::activateContext() {
- [EAGLContext setCurrentContext:reinterpret_cast<EAGLContext*>(glContext)];
-}
-void HeadlessBackend::deactivateContext() {
- [EAGLContext setCurrentContext:nil];
+ impl.reset(new EAGLImpl(glContext));
}
} // namespace mbgl
diff --git a/platform/darwin/src/headless_display_cgl.cpp b/platform/darwin/src/headless_display_cgl.cpp
new file mode 100644
index 0000000000..90d187d3db
--- /dev/null
+++ b/platform/darwin/src/headless_display_cgl.cpp
@@ -0,0 +1,52 @@
+#include <mbgl/gl/headless_display.hpp>
+
+#include <OpenGL/OpenGL.h>
+
+#include <stdexcept>
+#include <string>
+
+namespace mbgl {
+
+class HeadlessDisplay::Impl {
+public:
+ Impl();
+ ~Impl();
+ CGLPixelFormatObj pixelFormat = nullptr;
+};
+
+HeadlessDisplay::Impl::Impl() {
+ // TODO: test if OpenGL 4.1 with GL_ARB_ES2_compatibility is supported
+ // If it is, use kCGLOGLPVersion_3_2_Core and enable that extension.
+ CGLPixelFormatAttribute attributes[] = {
+ kCGLPFAOpenGLProfile,
+ static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_Legacy),
+ static_cast<CGLPixelFormatAttribute>(0)
+ };
+
+ GLint num;
+ CGLError error = CGLChoosePixelFormat(attributes, &pixelFormat, &num);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Error choosing pixel format:") + CGLErrorString(error) + "\n");
+ }
+ if (num <= 0) {
+ throw std::runtime_error("No pixel formats found.");
+ }
+}
+
+HeadlessDisplay::Impl::~Impl() {
+ CGLDestroyPixelFormat(pixelFormat);
+}
+
+template <>
+CGLPixelFormatObj HeadlessDisplay::attribute() const {
+ return impl->pixelFormat;
+}
+
+HeadlessDisplay::HeadlessDisplay()
+ : impl(std::make_unique<Impl>()) {
+}
+
+HeadlessDisplay::~HeadlessDisplay() {
+}
+
+} // namespace mbgl
diff --git a/platform/darwin/src/image.mm b/platform/darwin/src/image.mm
index 066535a58c..3a707d4a36 100644
--- a/platform/darwin/src/image.mm
+++ b/platform/darwin/src/image.mm
@@ -11,7 +11,7 @@
namespace mbgl {
std::string encodePNG(const PremultipliedImage& src) {
- CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, src.data.get(), src.size(), NULL);
+ CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, src.data.get(), src.bytes(), NULL);
if (!provider) {
return "";
}
@@ -22,9 +22,10 @@ std::string encodePNG(const PremultipliedImage& src) {
return "";
}
- CGImageRef image = CGImageCreate(src.width, src.height, 8, 32, 4 * src.width, color_space,
- kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast, provider, NULL, false,
- kCGRenderingIntentDefault);
+ CGImageRef image =
+ CGImageCreate(src.size.width, src.size.height, 8, 32, 4 * src.size.width, color_space,
+ kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast, provider, NULL,
+ false, kCGRenderingIntentDefault);
if (!image) {
CGColorSpaceRelease(color_space);
CGDataProviderRelease(provider);
@@ -92,11 +93,12 @@ PremultipliedImage decodeImage(const std::string &source_data) {
throw std::runtime_error("CGColorSpaceCreateDeviceRGB failed");
}
- PremultipliedImage result{ static_cast<uint16_t>(CGImageGetWidth(image)),
- static_cast<uint16_t>(CGImageGetHeight(image)) };
+ PremultipliedImage result({ static_cast<uint32_t>(CGImageGetWidth(image)),
+ static_cast<uint32_t>(CGImageGetHeight(image)) });
- CGContextRef context = CGBitmapContextCreate(result.data.get(), result.width, result.height, 8, result.stride(),
- color_space, kCGImageAlphaPremultipliedLast);
+ CGContextRef context =
+ CGBitmapContextCreate(result.data.get(), result.size.width, result.size.height, 8,
+ result.stride(), color_space, kCGImageAlphaPremultipliedLast);
if (!context) {
CGColorSpaceRelease(color_space);
CGImageRelease(image);
@@ -107,7 +109,9 @@ PremultipliedImage decodeImage(const std::string &source_data) {
CGContextSetBlendMode(context, kCGBlendModeCopy);
- CGRect rect = {{ 0, 0 }, { static_cast<CGFloat>(result.width), static_cast<CGFloat>(result.height) }};
+ CGRect rect = { { 0, 0 },
+ { static_cast<CGFloat>(result.size.width),
+ static_cast<CGFloat>(result.size.height) } };
CGContextDrawImage(context, rect, image);
CGContextRelease(context);
diff --git a/platform/darwin/src/log_nslog.mm b/platform/darwin/src/logging_nslog.mm
index 49583ae3c4..dd428f56b1 100644
--- a/platform/darwin/src/log_nslog.mm
+++ b/platform/darwin/src/logging_nslog.mm
@@ -1,4 +1,4 @@
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/enum.hpp>
#import <Foundation/Foundation.h>
diff --git a/platform/darwin/src/nsthread.mm b/platform/darwin/src/nsthread.mm
index eee6d6991b..6caa1be43e 100644
--- a/platform/darwin/src/nsthread.mm
+++ b/platform/darwin/src/nsthread.mm
@@ -1,6 +1,6 @@
#import <Foundation/Foundation.h>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/platform.hpp>
#include <pthread.h>
diff --git a/platform/darwin/src/string_nsstring.mm b/platform/darwin/src/string_nsstring.mm
index 9bf199afc0..08f9aeccef 100644
--- a/platform/darwin/src/string_nsstring.mm
+++ b/platform/darwin/src/string_nsstring.mm
@@ -1,6 +1,6 @@
#import <Foundation/Foundation.h>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/platform.hpp>
namespace mbgl {
namespace platform {
diff --git a/platform/darwin/test/MGLBackgroundStyleLayerTests.mm b/platform/darwin/test/MGLBackgroundStyleLayerTests.mm
index ec962ae502..60a332a5e7 100644
--- a/platform/darwin/test/MGLBackgroundStyleLayerTests.mm
+++ b/platform/darwin/test/MGLBackgroundStyleLayerTests.mm
@@ -30,7 +30,7 @@
MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.backgroundColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getBackgroundColor(), propertyValue,
@"Setting backgroundColor to a constant value should update background-color.");
XCTAssertEqualObjects(layer.backgroundColor, styleValue,
diff --git a/platform/darwin/test/MGLCircleStyleLayerTests.mm b/platform/darwin/test/MGLCircleStyleLayerTests.mm
index 1f4b82e32b..35e29b31d5 100644
--- a/platform/darwin/test/MGLCircleStyleLayerTests.mm
+++ b/platform/darwin/test/MGLCircleStyleLayerTests.mm
@@ -85,7 +85,7 @@
MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.circleColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
@"Setting circleColor to a constant value should update circle-color.");
XCTAssertEqualObjects(layer.circleColor, styleValue,
@@ -213,6 +213,108 @@
@"circleScaleAlignment should return the default value after being unset.");
}
+ // circle-stroke-color
+ {
+ XCTAssertTrue(rawLayer->getCircleStrokeColor().isUndefined(),
+ @"circle-stroke-color should be unset initially.");
+ MGLStyleValue<MGLColor *> *defaultStyleValue = layer.circleStrokeColor;
+
+ MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
+ layer.circleStrokeColor = styleValue;
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
+ XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
+ @"Setting circleStrokeColor to a constant value should update circle-stroke-color.");
+ XCTAssertEqualObjects(layer.circleStrokeColor, styleValue,
+ @"circleStrokeColor should round-trip constant values.");
+
+ styleValue = [MGLStyleValue<MGLColor *> valueWithStops:@{
+ @18: styleValue,
+ }];
+ layer.circleStrokeColor = styleValue;
+ propertyValue = { mbgl::style::Function<mbgl::Color> {
+ {{ 18, propertyValue.asConstant() }},
+ 1,
+ }};
+ XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
+ @"Setting circleStrokeColor to a function should update circle-stroke-color.");
+ XCTAssertEqualObjects(layer.circleStrokeColor, styleValue,
+ @"circleStrokeColor should round-trip functions.");
+
+ layer.circleStrokeColor = nil;
+ XCTAssertTrue(rawLayer->getCircleStrokeColor().isUndefined(),
+ @"Unsetting circleStrokeColor should return circle-stroke-color to the default value.");
+ XCTAssertEqualObjects(layer.circleStrokeColor, defaultStyleValue,
+ @"circleStrokeColor should return the default value after being unset.");
+ }
+
+ // circle-stroke-opacity
+ {
+ XCTAssertTrue(rawLayer->getCircleStrokeOpacity().isUndefined(),
+ @"circle-stroke-opacity should be unset initially.");
+ MGLStyleValue<NSNumber *> *defaultStyleValue = layer.circleStrokeOpacity;
+
+ MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.circleStrokeOpacity = styleValue;
+ mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
+ @"Setting circleStrokeOpacity to a constant value should update circle-stroke-opacity.");
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, styleValue,
+ @"circleStrokeOpacity should round-trip constant values.");
+
+ styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
+ @18: styleValue,
+ }];
+ layer.circleStrokeOpacity = styleValue;
+ propertyValue = { mbgl::style::Function<float> {
+ {{ 18, propertyValue.asConstant() }},
+ 1,
+ }};
+ XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
+ @"Setting circleStrokeOpacity to a function should update circle-stroke-opacity.");
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, styleValue,
+ @"circleStrokeOpacity should round-trip functions.");
+
+ layer.circleStrokeOpacity = nil;
+ XCTAssertTrue(rawLayer->getCircleStrokeOpacity().isUndefined(),
+ @"Unsetting circleStrokeOpacity should return circle-stroke-opacity to the default value.");
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, defaultStyleValue,
+ @"circleStrokeOpacity should return the default value after being unset.");
+ }
+
+ // circle-stroke-width
+ {
+ XCTAssertTrue(rawLayer->getCircleStrokeWidth().isUndefined(),
+ @"circle-stroke-width should be unset initially.");
+ MGLStyleValue<NSNumber *> *defaultStyleValue = layer.circleStrokeWidth;
+
+ MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.circleStrokeWidth = styleValue;
+ mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
+ @"Setting circleStrokeWidth to a constant value should update circle-stroke-width.");
+ XCTAssertEqualObjects(layer.circleStrokeWidth, styleValue,
+ @"circleStrokeWidth should round-trip constant values.");
+
+ styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
+ @18: styleValue,
+ }];
+ layer.circleStrokeWidth = styleValue;
+ propertyValue = { mbgl::style::Function<float> {
+ {{ 18, propertyValue.asConstant() }},
+ 1,
+ }};
+ XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
+ @"Setting circleStrokeWidth to a function should update circle-stroke-width.");
+ XCTAssertEqualObjects(layer.circleStrokeWidth, styleValue,
+ @"circleStrokeWidth should round-trip functions.");
+
+ layer.circleStrokeWidth = nil;
+ XCTAssertTrue(rawLayer->getCircleStrokeWidth().isUndefined(),
+ @"Unsetting circleStrokeWidth should return circle-stroke-width to the default value.");
+ XCTAssertEqualObjects(layer.circleStrokeWidth, defaultStyleValue,
+ @"circleStrokeWidth should return the default value after being unset.");
+ }
+
// circle-translate
{
XCTAssertTrue(rawLayer->getCircleTranslate().isUndefined(),
@@ -294,6 +396,9 @@
[self testPropertyName:@"circle-opacity" isBoolean:NO];
[self testPropertyName:@"circle-radius" isBoolean:NO];
[self testPropertyName:@"circle-scale-alignment" isBoolean:NO];
+ [self testPropertyName:@"circle-stroke-color" isBoolean:NO];
+ [self testPropertyName:@"circle-stroke-opacity" isBoolean:NO];
+ [self testPropertyName:@"circle-stroke-width" isBoolean:NO];
[self testPropertyName:@"circle-translation" isBoolean:NO];
[self testPropertyName:@"circle-translation-anchor" isBoolean:NO];
}
diff --git a/platform/darwin/test/MGLFeatureTests.mm b/platform/darwin/test/MGLFeatureTests.mm
index 7d60f53faa..91ec9d429e 100644
--- a/platform/darwin/test/MGLFeatureTests.mm
+++ b/platform/darwin/test/MGLFeatureTests.mm
@@ -91,7 +91,7 @@
mbgl::Point<double> point = { -90.066667, 29.95 };
mbgl::Feature pointFeature { point };
pointFeature.id = { UINT64_MAX };
- pointFeature.properties["null"] = nullptr;
+ pointFeature.properties["null"] = mapbox::geometry::null_value;
pointFeature.properties["bool"] = true;
pointFeature.properties["unsigned int"] = UINT64_MAX;
pointFeature.properties["int"] = INT64_MIN;
diff --git a/platform/darwin/test/MGLFillStyleLayerTests.mm b/platform/darwin/test/MGLFillStyleLayerTests.mm
index 869ad4f9b5..fb50512afd 100644
--- a/platform/darwin/test/MGLFillStyleLayerTests.mm
+++ b/platform/darwin/test/MGLFillStyleLayerTests.mm
@@ -85,7 +85,7 @@
MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.fillColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
@"Setting fillColor to a constant value should update fill-color.");
XCTAssertEqualObjects(layer.fillColor, styleValue,
@@ -153,7 +153,7 @@
MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.fillOutlineColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
@"Setting fillOutlineColor to a constant value should update fill-outline-color.");
XCTAssertEqualObjects(layer.fillOutlineColor, styleValue,
diff --git a/platform/darwin/test/MGLLineStyleLayerTests.mm b/platform/darwin/test/MGLLineStyleLayerTests.mm
index 1abe1cf6c3..24a9d7afea 100644
--- a/platform/darwin/test/MGLLineStyleLayerTests.mm
+++ b/platform/darwin/test/MGLLineStyleLayerTests.mm
@@ -221,7 +221,7 @@
MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.lineColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
@"Setting lineColor to a constant value should update line-color.");
XCTAssertEqualObjects(layer.lineColor, styleValue,
diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
index c4dee559fc..80a9c9d3ec 100644
--- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm
+++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
@@ -1225,7 +1225,7 @@
MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.iconColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
@"Setting iconColor to a constant value should update icon-color.");
XCTAssertEqualObjects(layer.iconColor, styleValue,
@@ -1293,7 +1293,7 @@
MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.iconHaloColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
@"Setting iconHaloColor to a constant value should update icon-halo-color.");
XCTAssertEqualObjects(layer.iconHaloColor, styleValue,
@@ -1469,7 +1469,7 @@
MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.textColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
@"Setting textColor to a constant value should update text-color.");
XCTAssertEqualObjects(layer.textColor, styleValue,
@@ -1537,7 +1537,7 @@
MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.textHaloColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
@"Setting textHaloColor to a constant value should update text-halo-color.");
XCTAssertEqualObjects(layer.textHaloColor, styleValue,
diff --git a/platform/darwin/test/MGLVersionNumber.m b/platform/darwin/test/MGLVersionNumber.m
new file mode 100644
index 0000000000..fae08a087d
--- /dev/null
+++ b/platform/darwin/test/MGLVersionNumber.m
@@ -0,0 +1,15 @@
+#import <Mapbox/Mapbox.h>
+
+#import <XCTest/XCTest.h>
+
+@interface MGLVersionTests : XCTestCase
+
+@end
+
+@implementation MGLVersionTests
+
+- (void)testVersionNumber {
+ XCTAssertEqual(1, MapboxVersionNumber);
+}
+
+@end
diff --git a/platform/default/bidi.cpp b/platform/default/bidi.cpp
new file mode 100644
index 0000000000..25b4dbe3a7
--- /dev/null
+++ b/platform/default/bidi.cpp
@@ -0,0 +1,127 @@
+#include <memory>
+
+#include <mbgl/text/bidi.hpp>
+#include <unicode/ubidi.h>
+#include <unicode/ushape.h>
+
+namespace mbgl {
+
+class BiDiImpl {
+public:
+ BiDiImpl() : bidiText(ubidi_open()), bidiLine(ubidi_open()) {
+ }
+ ~BiDiImpl() {
+ ubidi_close(bidiText);
+ ubidi_close(bidiLine);
+ }
+
+ UBiDi* bidiText = nullptr;
+ UBiDi* bidiLine = nullptr;
+};
+
+BiDi::BiDi() : impl(std::make_unique<BiDiImpl>()) {}
+BiDi::~BiDi() = default;
+
+// Takes UTF16 input in logical order and applies Arabic shaping to the input while maintaining
+// logical order. Output won't be intelligible until the bidirectional algorithm is applied
+std::u16string applyArabicShaping(const std::u16string& input) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+
+ const int32_t outputLength =
+ u_shapeArabic(input.c_str(), static_cast<int32_t>(input.size()), NULL, 0,
+ (U_SHAPE_LETTERS_SHAPE & U_SHAPE_LETTERS_MASK) |
+ (U_SHAPE_TEXT_DIRECTION_LOGICAL & U_SHAPE_TEXT_DIRECTION_MASK),
+ &errorCode);
+
+ // Pre-flighting will always set U_BUFFER_OVERFLOW_ERROR
+ errorCode = U_ZERO_ERROR;
+
+ auto outputText = std::make_unique<UChar[]>(outputLength);
+ u_shapeArabic(input.c_str(), static_cast<int32_t>(input.size()), outputText.get(), outputLength,
+ (U_SHAPE_LETTERS_SHAPE & U_SHAPE_LETTERS_MASK) |
+ (U_SHAPE_TEXT_DIRECTION_LOGICAL & U_SHAPE_TEXT_DIRECTION_MASK),
+ &errorCode);
+
+ // If the algorithm fails for any reason, fall back to non-transformed text
+ if (U_FAILURE(errorCode))
+ return input;
+
+ return std::u16string(outputText.get(), outputLength);
+}
+
+void BiDi::mergeParagraphLineBreaks(std::set<size_t>& lineBreakPoints) {
+ int32_t paragraphCount = ubidi_countParagraphs(impl->bidiText);
+ for (int32_t i = 0; i < paragraphCount; i++) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ int32_t paragraphEndIndex;
+ ubidi_getParagraphByIndex(impl->bidiText, i, NULL, &paragraphEndIndex, NULL, &errorCode);
+
+ if (U_FAILURE(errorCode)) {
+ throw std::runtime_error(std::string("ProcessedBiDiText::mergeParagraphLineBreaks: ") +
+ u_errorName(errorCode));
+ }
+
+ lineBreakPoints.insert(static_cast<std::size_t>(paragraphEndIndex));
+ }
+}
+
+std::vector<std::u16string> BiDi::applyLineBreaking(std::set<std::size_t> lineBreakPoints) {
+ // BiDi::getLine will error if called across a paragraph boundary, so we need to ensure that all
+ // paragraph boundaries are included in the set of line break points. The calling code might not
+ // include the line break because it didn't need to wrap at that point, or because the text was
+ // separated with a more exotic code point such as (U+001C)
+ mergeParagraphLineBreaks(lineBreakPoints);
+
+ std::vector<std::u16string> transformedLines;
+ std::size_t start = 0;
+ for (std::size_t lineBreakPoint : lineBreakPoints) {
+ transformedLines.push_back(getLine(start, lineBreakPoint));
+ start = lineBreakPoint;
+ }
+
+ return transformedLines;
+}
+
+std::vector<std::u16string> BiDi::processText(const std::u16string& input,
+ std::set<std::size_t> lineBreakPoints) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+
+ ubidi_setPara(impl->bidiText, input.c_str(), static_cast<int32_t>(input.size()),
+ UBIDI_DEFAULT_LTR, NULL, &errorCode);
+
+ if (U_FAILURE(errorCode)) {
+ throw std::runtime_error(std::string("BiDi::processText: ") + u_errorName(errorCode));
+ }
+
+ return applyLineBreaking(lineBreakPoints);
+}
+
+std::u16string BiDi::getLine(std::size_t start, std::size_t end) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ ubidi_setLine(impl->bidiText, static_cast<int32_t>(start), static_cast<int32_t>(end), impl->bidiLine, &errorCode);
+
+ if (U_FAILURE(errorCode)) {
+ throw std::runtime_error(std::string("BiDi::getLine (setLine): ") + u_errorName(errorCode));
+ }
+
+ // Because we set UBIDI_REMOVE_BIDI_CONTROLS, the output may be smaller than what we reserve
+ // Setting UBIDI_INSERT_LRM_FOR_NUMERIC would require
+ // ubidi_getLength(pBiDi)+2*ubidi_countRuns(pBiDi)
+ const int32_t outputLength = ubidi_getProcessedLength(impl->bidiLine);
+ auto outputText = std::make_unique<UChar[]>(outputLength);
+
+ // UBIDI_DO_MIRRORING: Apply unicode mirroring of characters like parentheses
+ // UBIDI_REMOVE_BIDI_CONTROLS: Now that all the lines are set, remove control characters so that
+ // they don't show up on screen (some fonts have glyphs representing them)
+ ubidi_writeReordered(impl->bidiLine, outputText.get(), outputLength,
+ UBIDI_DO_MIRRORING | UBIDI_REMOVE_BIDI_CONTROLS, &errorCode);
+
+ if (U_FAILURE(errorCode)) {
+ throw std::runtime_error(std::string("BiDi::getLine (writeReordered): ") +
+ u_errorName(errorCode));
+ }
+
+ return std::u16string(outputText.get(), outputLength);
+}
+
+} // end namespace mbgl
diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp
index 7b52637c15..c4222b5a12 100644
--- a/platform/default/default_file_source.cpp
+++ b/platform/default/default_file_source.cpp
@@ -5,7 +5,7 @@
#include <mbgl/storage/offline_database.hpp>
#include <mbgl/storage/offline_download.hpp>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/platform.hpp>
#include <mbgl/util/url.hpp>
#include <mbgl/util/thread.hpp>
#include <mbgl/util/work_request.hpp>
diff --git a/platform/default/headless_backend_glx.cpp b/platform/default/headless_backend_glx.cpp
deleted file mode 100644
index bbfd19345b..0000000000
--- a/platform/default/headless_backend_glx.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-
-#include <mbgl/platform/log.hpp>
-
-// #include <cassert>
-
-#include <GL/glx.h>
-
-namespace mbgl {
-
-gl::glProc HeadlessBackend::initializeExtension(const char* name) {
- return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
-}
-
-void HeadlessBackend::createContext() {
- xDisplay = display->xDisplay;
- fbConfigs = display->fbConfigs;
-
- if (!glContext) {
- // Try to create a legacy context
- glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, None, True);
- if (glContext) {
- if (!glXIsDirect(xDisplay, glContext)) {
- Log::Error(Event::OpenGL, "failed to create direct OpenGL Legacy context");
- glXDestroyContext(xDisplay, glContext);
- glContext = nullptr;
- }
- }
- }
-
- if (glContext == nullptr) {
- throw std::runtime_error("Error creating GL context object.");
- }
-
- // Create a dummy pbuffer. We will render to framebuffers anyway, but we need a pbuffer to
- // activate the context.
- int pbufferAttributes[] = {
- GLX_PBUFFER_WIDTH, 8,
- GLX_PBUFFER_HEIGHT, 8,
- None
- };
- glxPbuffer = glXCreatePbuffer(xDisplay, fbConfigs[0], pbufferAttributes);
-}
-
-void HeadlessBackend::destroyContext() {
- if (glxPbuffer) {
- glXDestroyPbuffer(xDisplay, glxPbuffer);
- glxPbuffer = 0;
- }
-
- glXDestroyContext(xDisplay, glContext);
-}
-
-void HeadlessBackend::activateContext() {
- if (!glXMakeContextCurrent(xDisplay, glxPbuffer, glxPbuffer, glContext)) {
- throw std::runtime_error("Switching OpenGL context failed.\n");
- }
-}
-
-void HeadlessBackend::deactivateContext() {
- if (!glXMakeContextCurrent(xDisplay, 0, 0, nullptr)) {
- throw std::runtime_error("Removing OpenGL context failed.\n");
- }
-}
-
-} // namespace mbgl
diff --git a/platform/default/headless_backend_osmesa.cpp b/platform/default/headless_backend_osmesa.cpp
index e0e385fcc6..081bddf170 100644
--- a/platform/default/headless_backend_osmesa.cpp
+++ b/platform/default/headless_backend_osmesa.cpp
@@ -1,47 +1,54 @@
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/util/logging.hpp>
-namespace mbgl {
+#include <GL/osmesa.h>
-gl::glProc HeadlessBackend::initializeExtension(const char* name) {
- return OSMesaGetProcAddress(name);
-}
+#include <cassert>
-void HeadlessBackend::createContext() {
- if (glContext == nullptr) {
-#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
- glContext = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, nullptr);
-#else
- glContext = OSMesaCreateContext(OSMESA_RGBA, nullptr);
-#endif
- if (glContext == nullptr) {
- Log::Error(Event::OpenGL, "failed to create OSMesa context");
- }
- }
+namespace mbgl {
- if (glContext == nullptr) {
- throw std::runtime_error("Error creating GL context object.");
+struct OSMesaImpl : public HeadlessBackend::Impl {
+ OSMesaImpl(OSMesaContext glContext_) : glContext(glContext_) {
}
-}
-void HeadlessBackend::destroyContext() {
- if (glContext) {
+ ~OSMesaImpl() {
if (glContext != OSMesaGetCurrentContext()) {
activateContext();
}
OSMesaDestroyContext(glContext);
- glContext = nullptr;
}
-}
-void HeadlessBackend::activateContext() {
- if (!OSMesaMakeCurrent(glContext, &fakeBuffer, GL_UNSIGNED_BYTE, 1, 1)) {
- throw std::runtime_error("Switching OpenGL context failed.\n");
+ void activateContext() final {
+ if (!OSMesaMakeCurrent(glContext, &fakeBuffer, GL_UNSIGNED_BYTE, 1, 1)) {
+ throw std::runtime_error("Switching OpenGL context failed.\n");
+ }
}
+
+ OSMesaContext glContext = nullptr;
+ GLubyte fakeBuffer = 0;
+};
+
+gl::glProc HeadlessBackend::initializeExtension(const char* name) {
+ return OSMesaGetProcAddress(name);
}
-void HeadlessBackend::deactivateContext() {
- // no-op.
+bool HeadlessBackend::hasDisplay() {
+ return true;
+};
+
+void HeadlessBackend::createContext() {
+ assert(!hasContext());
+
+#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
+ OSMesaContext glContext = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, nullptr);
+#else
+ OSMesaContext glContext = OSMesaCreateContext(OSMESA_RGBA, nullptr);
+#endif
+ if (glContext == nullptr) {
+ throw std::runtime_error("Error creating GL context object.");
+ }
+
+ impl.reset(new OSMesaImpl(glContext));
}
} // namespace mbgl
diff --git a/platform/default/http_file_source.cpp b/platform/default/http_file_source.cpp
index ce6987fbdd..867d85fa4d 100644
--- a/platform/default/http_file_source.cpp
+++ b/platform/default/http_file_source.cpp
@@ -1,7 +1,7 @@
#include <mbgl/storage/http_file_source.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/util.hpp>
#include <mbgl/util/optional.hpp>
diff --git a/platform/default/image.cpp b/platform/default/image.cpp
index 890d442683..84db1e9c71 100644
--- a/platform/default/image.cpp
+++ b/platform/default/image.cpp
@@ -25,8 +25,8 @@ const static bool png_version_check __attribute__((unused)) = []() {
namespace mbgl {
std::string encodePNG(const PremultipliedImage& pre) {
- PremultipliedImage copy { pre.width, pre.height };
- std::copy(pre.data.get(), pre.data.get() + pre.size(), copy.data.get());
+ PremultipliedImage copy(pre.size);
+ std::copy(pre.data.get(), pre.data.get() + pre.bytes(), copy.data.get());
UnassociatedImage src = util::unpremultiply(std::move(copy));
@@ -42,8 +42,8 @@ std::string encodePNG(const PremultipliedImage& pre) {
throw std::runtime_error("couldn't create info_ptr");
}
- png_set_IHDR(png_ptr, info_ptr, src.width, src.height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+ png_set_IHDR(png_ptr, info_ptr, src.size.width, src.size.height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
jmp_buf *jmp_context = (jmp_buf *)png_get_error_ptr(png_ptr);
if (jmp_context) {
@@ -61,9 +61,9 @@ std::string encodePNG(const PremultipliedImage& pre) {
ptrs(size_t count) : rows(new png_bytep[count]) {}
~ptrs() { delete[] rows; }
png_bytep *rows = nullptr;
- } pointers(src.height);
+ } pointers(src.size.height);
- for (size_t i = 0; i < src.height; i++) {
+ for (size_t i = 0; i < src.size.height; i++) {
pointers.rows[i] = src.data.get() + src.stride() * i;
}
diff --git a/platform/default/jpeg_reader.cpp b/platform/default/jpeg_reader.cpp
index 5151060a12..78c74f2fd7 100644
--- a/platform/default/jpeg_reader.cpp
+++ b/platform/default/jpeg_reader.cpp
@@ -119,7 +119,7 @@ PremultipliedImage decodeJPEG(const uint8_t* data, size_t size) {
size_t components = cinfo.output_components;
size_t rowStride = components * width;
- PremultipliedImage image { static_cast<uint16_t>(width), static_cast<uint16_t>(height) };
+ PremultipliedImage image({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
uint8_t* dst = image.data.get();
JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, rowStride, 1);
diff --git a/platform/default/log_stderr.cpp b/platform/default/logging_stderr.cpp
index 145cdeda03..41585fb7bb 100644
--- a/platform/default/log_stderr.cpp
+++ b/platform/default/logging_stderr.cpp
@@ -1,4 +1,4 @@
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/enum.hpp>
#include <iostream>
diff --git a/platform/default/headless_backend.cpp b/platform/default/mbgl/gl/headless_backend.cpp
index 279a7973c9..0bfdf11c98 100644
--- a/platform/default/headless_backend.cpp
+++ b/platform/default/mbgl/gl/headless_backend.cpp
@@ -1,17 +1,18 @@
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/headless_display.hpp>
#include <cassert>
#include <stdexcept>
+#include <type_traits>
namespace mbgl {
-HeadlessBackend::HeadlessBackend() : display(std::make_shared<HeadlessDisplay>()) {
+HeadlessBackend::HeadlessBackend() {
activate();
}
HeadlessBackend::HeadlessBackend(std::shared_ptr<HeadlessDisplay> display_)
- : display(std::move(display_)) {
+ : display(std::move(display_)) {
activate();
}
@@ -23,8 +24,8 @@ HeadlessBackend::~HeadlessBackend() {
void HeadlessBackend::activate() {
active = true;
- if (!glContext) {
- if (!display) {
+ if (!hasContext()) {
+ if (!hasDisplay()) {
throw std::runtime_error("Display is not set");
}
createContext();
@@ -47,6 +48,21 @@ void HeadlessBackend::invalidate() {
assert(false);
}
+void HeadlessBackend::destroyContext() {
+ assert(hasContext());
+ impl.reset();
+}
+
+void HeadlessBackend::activateContext() {
+ assert(hasContext());
+ impl->activateContext();
+}
+
+void HeadlessBackend::deactivateContext() {
+ assert(hasContext());
+ impl->deactivateContext();
+}
+
void HeadlessBackend::notifyMapChange(MapChange change) {
if (mapChangeCallback) {
mapChangeCallback(change);
diff --git a/include/mbgl/platform/default/headless_backend.hpp b/platform/default/mbgl/gl/headless_backend.hpp
index b6c654943f..da8c55e044 100644
--- a/include/mbgl/platform/default/headless_backend.hpp
+++ b/platform/default/mbgl/gl/headless_backend.hpp
@@ -1,23 +1,8 @@
#pragma once
-#include <mbgl/gl/implementation.hpp>
-
-#if MBGL_USE_QT
-class QGLWidget;
-#elif MBGL_USE_CGL
-#include <OpenGL/OpenGL.h>
-#elif MBGL_USE_GLX
-typedef struct _XDisplay Display;
-typedef struct __GLXcontextRec* GLXContext;
-typedef struct __GLXFBConfigRec* GLXFBConfig;
-typedef long unsigned int XID;
-typedef XID GLXPbuffer;
-#elif MBGL_USE_OSMESA
-#include <GL/osmesa.h>
-#endif
+#include <mbgl/gl/extension.hpp>
#include <mbgl/map/backend.hpp>
-#include <mbgl/gl/extension.hpp>
#include <memory>
#include <functional>
@@ -39,47 +24,34 @@ public:
void setMapChangeCallback(std::function<void(MapChange)>&& cb) { mapChangeCallback = std::move(cb); }
-private:
- void activateContext();
- void deactivateContext();
+ struct Impl {
+ virtual ~Impl() {}
+ virtual void activateContext() = 0;
+ virtual void deactivateContext() {}
+ };
private:
// Implementation specific functions
static gl::glProc initializeExtension(const char*);
+
+ bool hasContext() const { return bool(impl); }
+ bool hasDisplay();
+
void createContext();
+
+private:
void destroyContext();
+ void activateContext();
+ void deactivateContext();
+
+ std::unique_ptr<Impl> impl;
std::shared_ptr<HeadlessDisplay> display;
bool extensionsLoaded = false;
bool active = false;
-#if MBGL_USE_QT
- QGLWidget* glContext = nullptr;
-#endif
-
-#if MBGL_USE_CGL
- CGLContextObj glContext = nullptr;
-#endif
-
-#if MBGL_USE_EAGL
- void *glContext = nullptr;
-#endif
-
-#if MBGL_USE_GLX
- Display *xDisplay = nullptr;
- GLXFBConfig *fbConfigs = nullptr;
- GLXContext glContext = nullptr;
- GLXPbuffer glxPbuffer = 0;
-#endif
-
-#if MBGL_USE_OSMESA
- OSMesaContext glContext = nullptr;
- GLubyte fakeBuffer = 0;
-#endif
-
std::function<void(MapChange)> mapChangeCallback;
-
};
} // namespace mbgl
diff --git a/platform/default/mbgl/gl/headless_display.cpp b/platform/default/mbgl/gl/headless_display.cpp
new file mode 100644
index 0000000000..6247046c29
--- /dev/null
+++ b/platform/default/mbgl/gl/headless_display.cpp
@@ -0,0 +1,15 @@
+#include <mbgl/gl/headless_display.hpp>
+
+namespace mbgl {
+
+class HeadlessDisplay::Impl {};
+
+HeadlessDisplay::HeadlessDisplay() {
+ // no-op
+}
+
+HeadlessDisplay::~HeadlessDisplay() {
+ // no-op
+}
+
+} // namespace mbgl
diff --git a/platform/default/mbgl/gl/headless_display.hpp b/platform/default/mbgl/gl/headless_display.hpp
new file mode 100644
index 0000000000..a5c95085b8
--- /dev/null
+++ b/platform/default/mbgl/gl/headless_display.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <memory>
+
+namespace mbgl {
+
+class HeadlessDisplay {
+public:
+ HeadlessDisplay();
+ ~HeadlessDisplay();
+
+ template <typename DisplayAttribute>
+ DisplayAttribute attribute() const;
+
+private:
+ class Impl;
+ std::unique_ptr<Impl> impl;
+};
+
+} // namespace mbgl
diff --git a/platform/default/mbgl/gl/offscreen_view.cpp b/platform/default/mbgl/gl/offscreen_view.cpp
new file mode 100644
index 0000000000..16faf6a4a9
--- /dev/null
+++ b/platform/default/mbgl/gl/offscreen_view.cpp
@@ -0,0 +1,30 @@
+#include <mbgl/gl/offscreen_view.hpp>
+#include <mbgl/gl/context.hpp>
+
+#include <cstring>
+#include <cassert>
+
+namespace mbgl {
+
+OffscreenView::OffscreenView(gl::Context& context_, const Size size_)
+ : size(std::move(size_)), context(context_) {
+ assert(size);
+}
+
+void OffscreenView::bind() {
+ if (!framebuffer) {
+ color = context.createRenderbuffer<gl::RenderbufferType::RGBA>(size);
+ depthStencil = context.createRenderbuffer<gl::RenderbufferType::DepthStencil>(size);
+ framebuffer = context.createFramebuffer(*color, *depthStencil);
+ } else {
+ context.bindFramebuffer = framebuffer->framebuffer;
+ }
+
+ context.viewport = { 0, 0, size };
+}
+
+PremultipliedImage OffscreenView::readStillImage() {
+ return context.readFramebuffer<PremultipliedImage>(size);
+}
+
+} // namespace mbgl
diff --git a/include/mbgl/platform/default/offscreen_view.hpp b/platform/default/mbgl/gl/offscreen_view.hpp
index 034aa3aaf3..0e839e14cc 100644
--- a/include/mbgl/platform/default/offscreen_view.hpp
+++ b/platform/default/mbgl/gl/offscreen_view.hpp
@@ -14,17 +14,17 @@ class Context;
class OffscreenView : public View {
public:
- OffscreenView(gl::Context&, std::array<uint16_t, 2> size = {{ 256, 256 }});
+ OffscreenView(gl::Context&, Size size = { 256, 256 });
void bind() override;
PremultipliedImage readStillImage();
- std::array<uint16_t, 2> getSize() const;
+public:
+ const Size size;
private:
gl::Context& context;
- std::array<uint16_t, 2> size;
optional<gl::Framebuffer> framebuffer;
optional<gl::Renderbuffer<gl::RenderbufferType::RGBA>> color;
optional<gl::Renderbuffer<gl::RenderbufferType::DepthStencil>> depthStencil;
diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp
index 4bcc9ad711..73364b042f 100644
--- a/platform/default/mbgl/storage/offline_database.cpp
+++ b/platform/default/mbgl/storage/offline_database.cpp
@@ -4,7 +4,7 @@
#include <mbgl/util/io.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/chrono.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include "sqlite3.hpp"
#include <sqlite3.h>
diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp
index 9e2e11c86f..3edc75845c 100644
--- a/platform/default/mbgl/storage/offline_download.cpp
+++ b/platform/default/mbgl/storage/offline_download.cpp
@@ -184,7 +184,7 @@ void OfflineDownload::activateDownload() {
if (!parser.glyphURL.empty()) {
for (const auto& fontStack : parser.fontStacks()) {
- for (uint32_t i = 0; i < GLYPH_RANGES_PER_FONT_STACK; i++) {
+ for (char16_t i = 0; i < GLYPH_RANGES_PER_FONT_STACK; i++) {
queueResource(Resource::glyphs(parser.glyphURL, fontStack, getGlyphRange(i * GLYPHS_PER_GLYPH_RANGE)));
}
}
diff --git a/src/mbgl/util/default_styles.cpp b/platform/default/mbgl/util/default_styles.cpp
index 17cc2f5740..17cc2f5740 100644
--- a/src/mbgl/util/default_styles.cpp
+++ b/platform/default/mbgl/util/default_styles.cpp
diff --git a/include/mbgl/util/default_styles.hpp b/platform/default/mbgl/util/default_styles.hpp
index eb7e034722..eb7e034722 100644
--- a/include/mbgl/util/default_styles.hpp
+++ b/platform/default/mbgl/util/default_styles.hpp
diff --git a/platform/default/thread_pool.cpp b/platform/default/mbgl/util/default_thread_pool.cpp
index b7e02db157..92c0f06745 100644
--- a/platform/default/thread_pool.cpp
+++ b/platform/default/mbgl/util/default_thread_pool.cpp
@@ -1,4 +1,4 @@
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/actor/mailbox.hpp>
namespace mbgl {
diff --git a/include/mbgl/platform/default/thread_pool.hpp b/platform/default/mbgl/util/default_thread_pool.hpp
index a14d16d771..a14d16d771 100644
--- a/include/mbgl/platform/default/thread_pool.hpp
+++ b/platform/default/mbgl/util/default_thread_pool.hpp
diff --git a/platform/default/offscreen_view.cpp b/platform/default/offscreen_view.cpp
deleted file mode 100644
index eaf87d0f87..0000000000
--- a/platform/default/offscreen_view.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <mbgl/platform/default/offscreen_view.hpp>
-#include <mbgl/gl/context.hpp>
-#include <mbgl/gl/gl.hpp>
-
-#include <cstring>
-#include <cassert>
-
-namespace mbgl {
-
-OffscreenView::OffscreenView(gl::Context& context_, std::array<uint16_t, 2> size_)
- : context(context_), size(std::move(size_)) {
- assert(size[0] > 0 && size[1] > 0);
-}
-
-void OffscreenView::bind() {
- if (!framebuffer) {
- color = context.createRenderbuffer<gl::RenderbufferType::RGBA>(size);
- depthStencil = context.createRenderbuffer<gl::RenderbufferType::DepthStencil>(size);
- framebuffer = context.createFramebuffer(*color, *depthStencil);
- } else {
- context.bindFramebuffer = framebuffer->framebuffer;
- }
-
- context.viewport = { 0, 0, size[0], size[1] };
-}
-
-PremultipliedImage OffscreenView::readStillImage() {
- PremultipliedImage image { size[0], size[1] };
- MBGL_CHECK_ERROR(glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
-
- const auto stride = image.stride();
- auto tmp = std::make_unique<uint8_t[]>(stride);
- uint8_t* rgba = image.data.get();
- for (int i = 0, j = size[1] - 1; i < j; i++, j--) {
- std::memcpy(tmp.get(), rgba + i * stride, stride);
- std::memcpy(rgba + i * stride, rgba + j * stride, stride);
- std::memcpy(rgba + j * stride, tmp.get(), stride);
- }
-
- return image;
-}
-
-std::array<uint16_t, 2> OffscreenView::getSize() const {
- return size;
-}
-
-} // namespace mbgl
diff --git a/platform/default/online_file_source.cpp b/platform/default/online_file_source.cpp
index 4f191f6cf7..0f2bc5ff56 100644
--- a/platform/default/online_file_source.cpp
+++ b/platform/default/online_file_source.cpp
@@ -3,7 +3,7 @@
#include <mbgl/storage/network_status.hpp>
#include <mbgl/storage/response.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/thread.hpp>
diff --git a/platform/default/png_reader.cpp b/platform/default/png_reader.cpp
index 5111edaa59..5ae74d74db 100644
--- a/platform/default/png_reader.cpp
+++ b/platform/default/png_reader.cpp
@@ -1,7 +1,7 @@
#include <mbgl/util/image.hpp>
#include <mbgl/util/premultiply.hpp>
#include <mbgl/util/char_array_buffer.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <istream>
#include <sstream>
@@ -80,7 +80,7 @@ PremultipliedImage decodePNG(const uint8_t* data, size_t size) {
int color_type = 0;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, nullptr, nullptr, nullptr);
- UnassociatedImage image { static_cast<uint16_t>(width), static_cast<uint16_t>(height) };
+ UnassociatedImage image({ width, height });
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png_ptr);
diff --git a/platform/default/sqlite3.cpp b/platform/default/sqlite3.cpp
index 578e407739..670b7b84cc 100644
--- a/platform/default/sqlite3.cpp
+++ b/platform/default/sqlite3.cpp
@@ -7,7 +7,7 @@
#include <chrono>
#include <experimental/optional>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
namespace mapbox {
namespace sqlite {
diff --git a/platform/default/string_stdlib.cpp b/platform/default/string_stdlib.cpp
index 90a75c1738..2642e88aff 100644
--- a/platform/default/string_stdlib.cpp
+++ b/platform/default/string_stdlib.cpp
@@ -1,10 +1,10 @@
-#include <mbgl/platform/platform.hpp>
-#include <mbgl/util/utf.hpp>
+#include <mbgl/util/platform.hpp>
#define NU_WITH_TOUPPER
#define NU_WITH_TOLOWER
#define NU_WITH_UTF8_WRITER
#include <libnu/libnu.h>
#include <cstring>
+#include <sstream>
namespace mbgl { namespace platform {
diff --git a/platform/default/thread.cpp b/platform/default/thread.cpp
index f4d0b9a855..c7c79b4fb0 100644
--- a/platform/default/thread.cpp
+++ b/platform/default/thread.cpp
@@ -1,5 +1,5 @@
-#include <mbgl/platform/platform.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/platform.hpp>
+#include <mbgl/util/logging.hpp>
#include <string>
diff --git a/platform/default/webp_reader.cpp b/platform/default/webp_reader.cpp
index 6f90fe02f5..2c01fb4479 100644
--- a/platform/default/webp_reader.cpp
+++ b/platform/default/webp_reader.cpp
@@ -1,6 +1,6 @@
#include <mbgl/util/image.hpp>
#include <mbgl/util/premultiply.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
extern "C"
{
@@ -23,8 +23,8 @@ PremultipliedImage decodeWebP(const uint8_t* data, size_t size) {
throw std::runtime_error("failed to decode WebP data");
}
- UnassociatedImage image{ static_cast<uint16_t>(width), static_cast<uint16_t>(height),
- std::move(webp) };
+ UnassociatedImage image({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) },
+ std::move(webp));
return util::premultiply(std::move(image));
}
diff --git a/platform/default/glfw_view.cpp b/platform/glfw/glfw_view.cpp
index 47551d786f..fdf82fda8f 100644
--- a/platform/default/glfw_view.cpp
+++ b/platform/glfw/glfw_view.cpp
@@ -1,12 +1,13 @@
-#include <mbgl/platform/default/glfw_view.hpp>
+#include "glfw_view.hpp"
+
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/style/transition_options.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/extension.hpp>
#include <mbgl/gl/context.hpp>
-#include <mbgl/platform/log.hpp>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/logging.hpp>
+#include <mbgl/util/platform.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/map/camera.hpp>
@@ -132,14 +133,14 @@ void GLFWView::setMap(mbgl::Map *map_) {
void GLFWView::updateViewBinding() {
getContext().bindFramebuffer.setCurrentValue(0);
- getContext().viewport.setCurrentValue(
- { 0, 0, static_cast<uint16_t>(fbWidth), static_cast<uint16_t>(fbHeight) });
+ assert(mbgl::gl::value::BindFramebuffer::Get() == getContext().bindFramebuffer.getCurrentValue());
+ getContext().viewport.setCurrentValue({ 0, 0, getFramebufferSize() });
+ assert(mbgl::gl::value::Viewport::Get() == getContext().viewport.getCurrentValue());
}
void GLFWView::bind() {
getContext().bindFramebuffer = 0;
- getContext().viewport = { 0, 0, static_cast<uint16_t>(fbWidth),
- static_cast<uint16_t>(fbHeight) };
+ getContext().viewport = { 0, 0, getFramebufferSize() };
}
void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, int mods) {
@@ -172,6 +173,7 @@ void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action,
}
}
break;
+#if not MBGL_USE_GLES2
case GLFW_KEY_B: {
auto debug = view->map->getDebug();
if (debug & mbgl::MapDebugOptions::StencilClip) {
@@ -184,6 +186,7 @@ void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action,
}
view->map->setDebug(debug);
} break;
+#endif // MBGL_USE_GLES2
case GLFW_KEY_N:
if (!mods)
view->map->resetNorth();
@@ -192,7 +195,7 @@ void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action,
view->nextOrientation();
break;
case GLFW_KEY_Q: {
- auto result = view->map->queryPointAnnotations({ {}, { double(view->getSize()[0]), double(view->getSize()[1]) } });
+ auto result = view->map->queryPointAnnotations({ {}, { double(view->getSize().width), double(view->getSize().height) } });
printf("visible point annotations: %lu\n", result.size());
} break;
case GLFW_KEY_C:
@@ -267,7 +270,7 @@ GLFWView::makeSpriteImage(int width, int height, float pixelRatio) {
const int w = std::ceil(pixelRatio * width);
const int h = std::ceil(pixelRatio * height);
- mbgl::PremultipliedImage image(w, h);
+ mbgl::PremultipliedImage image({ static_cast<uint32_t>(w), static_cast<uint32_t>(h) });
auto data = reinterpret_cast<uint32_t*>(image.data.get());
const int dist = (w / 2) * (w / 2);
for (int y = 0; y < h; y++) {
@@ -374,8 +377,7 @@ void GLFWView::onWindowResize(GLFWwindow *window, int width, int height) {
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
view->width = width;
view->height = height;
- view->map->setSize({{ static_cast<uint16_t>(view->width),
- static_cast<uint16_t>(view->height) }});
+ view->map->setSize({ static_cast<uint32_t>(view->width), static_cast<uint32_t>(view->height) });
}
void GLFWView::onFramebufferResize(GLFWwindow *window, int width, int height) {
@@ -480,12 +482,12 @@ float GLFWView::getPixelRatio() const {
return pixelRatio;
}
-std::array<uint16_t, 2> GLFWView::getSize() const {
- return {{ static_cast<uint16_t>(width), static_cast<uint16_t>(height) }};
+mbgl::Size GLFWView::getSize() const {
+ return { static_cast<uint32_t>(width), static_cast<uint32_t>(height) };
}
-std::array<uint16_t, 2> GLFWView::getFramebufferSize() const {
- return {{ static_cast<uint16_t>(fbWidth), static_cast<uint16_t>(fbHeight) }};
+mbgl::Size GLFWView::getFramebufferSize() const {
+ return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) };
}
void GLFWView::activate() {
diff --git a/include/mbgl/platform/default/glfw_view.hpp b/platform/glfw/glfw_view.hpp
index e832cd70d1..672fa2e13c 100644
--- a/include/mbgl/platform/default/glfw_view.hpp
+++ b/platform/glfw/glfw_view.hpp
@@ -1,6 +1,7 @@
#pragma once
-#include <mbgl/mbgl.hpp>
+#include <mbgl/map/map.hpp>
+#include <mbgl/map/view.hpp>
#include <mbgl/map/backend.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/timer.hpp>
@@ -34,8 +35,8 @@ public:
// mbgl::View implementation
void updateViewBinding();
void bind() override;
- std::array<uint16_t, 2> getSize() const;
- std::array<uint16_t, 2> getFramebufferSize() const;
+ mbgl::Size getSize() const;
+ mbgl::Size getFramebufferSize() const;
// mbgl::Backend implementation
void activate() override;
diff --git a/bin/glfw.cpp b/platform/glfw/main.cpp
index b51846b4e8..1f683b185f 100644
--- a/bin/glfw.cpp
+++ b/platform/glfw/main.cpp
@@ -1,10 +1,10 @@
-#include <mbgl/mbgl.hpp>
+#include "glfw_view.hpp"
+#include "settings_json.hpp"
+
#include <mbgl/util/default_styles.hpp>
-#include <mbgl/platform/log.hpp>
-#include <mbgl/platform/platform.hpp>
-#include <mbgl/platform/default/settings_json.hpp>
-#include <mbgl/platform/default/glfw_view.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/util/logging.hpp>
+#include <mbgl/util/platform.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <signal.h>
diff --git a/platform/default/settings_json.cpp b/platform/glfw/settings_json.cpp
index ef53aa83e7..2ba1038dc7 100644
--- a/platform/default/settings_json.cpp
+++ b/platform/glfw/settings_json.cpp
@@ -1,4 +1,4 @@
-#include <mbgl/platform/default/settings_json.hpp>
+#include "settings_json.hpp"
#include <fstream>
namespace mbgl {
diff --git a/include/mbgl/platform/default/settings_json.hpp b/platform/glfw/settings_json.hpp
index eb23b28bc8..eb23b28bc8 100644
--- a/include/mbgl/platform/default/settings_json.hpp
+++ b/platform/glfw/settings_json.hpp
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index 0d11a923a8..00fdf9f2c1 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -2,6 +2,13 @@
Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started.
+## master
+
+* Labels written in Arabic, Hebrew, and other scripts are written right-to-left. Arabic characters are correctly shaped. ([#6984](https://github.com/mapbox/mapbox-gl-native/pull/6984), [#7123](https://github.com/mapbox/mapbox-gl-native/pull/7123))
+* Improved the line wrapping behavior of point-placed labels written in Chinese, Japanese, and Yi. ([#6828](https://github.com/mapbox/mapbox-gl-native/pull/6828))
+* Fixed an issue where translucent, non-view-backed point annotations along tile boundaries would be drawn darker than expected. ([#6832](https://github.com/mapbox/mapbox-gl-native/pull/6832))
+* Added a Simplified Chinese localization. ([#7316](https://github.com/mapbox/mapbox-gl-native/pull/7316))
+
## 3.4.0
### Packaging
@@ -68,7 +75,6 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
### Networking and offline maps
* Fixed an issue preventing an MGLMapView from loading tiles while an offline pack is downloading. ([#6446](https://github.com/mapbox/mapbox-gl-native/pull/6446))
-* Fixed a crash that sometimes occurred when initializing an MGLMapView. ([#5932](https://github.com/mapbox/mapbox-gl-native/pull/5932))
* Fixed a crash that could occur when the device is disconnected while downloading an offline pack. ([#6293](https://github.com/mapbox/mapbox-gl-native/pull/6293))
* Fixed a crash that occurred when encountering a rate-limit error in response to a network request. ([#6223](https://github.com/mapbox/mapbox-gl-native/pull/6223))
* Fixed an issue causing an MGLOfflinePack’s progress to continue to update after calling `-suspend`. ([#6186](https://github.com/mapbox/mapbox-gl-native/pull/6186))
diff --git a/platform/ios/DEVELOPING.md b/platform/ios/DEVELOPING.md
index 894bb83930..72ad84868e 100644
--- a/platform/ios/DEVELOPING.md
+++ b/platform/ios/DEVELOPING.md
@@ -77,6 +77,7 @@ To add any Objective-C type, constant, or member to the iOS SDK’s public inter
To add an Objective-C class, protocol, category, typedef, enumeration, or global constant to the iOS SDK’s public interface:
+1. _(Optional.)_ Add the macro `MGL_EXPORT` prior to the declaration for classes and global constants when adding them in shared headers located in `platform/darwin`. To use this macro, include `MGLFoundation.h`. You can check whether all public symbols are exported correctly by running `make check-public-symbols`.
1. _(Optional.)_ Add the type or constant’s name to the relevant category in the `custom_categories` section of [the jazzy configuration file](./jazzy.yml). This is required for classes and protocols and also recommended for any other type that is strongly associated with a particular class or protocol. If you leave out this step, the symbol will appear in an “Other” section in the generated HTML documentation’s table of contents.
1. _(Optional.)_ If the symbol would also be publicly exposed in the macOS SDK, consult [the companion macOS document](../macos/DEVELOPING.md#making-a-type-or-constant-public) for further instructions.
diff --git a/platform/ios/bitrise.yml b/platform/ios/bitrise.yml
index d8a9a4fcd0..93d1d4afd8 100644
--- a/platform/ios/bitrise.yml
+++ b/platform/ios/bitrise.yml
@@ -2,6 +2,8 @@
format_version: 1.0.0
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
trigger_map:
+- pattern: nightly-release
+ workflow: nightly-release
- pattern: "*"
is_pull_request_allowed: true
workflow: primary
@@ -72,3 +74,32 @@ workflows:
failed'
- icon_url: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-icon-128.png
- icon_url_on_error: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-error-icon-128.png
+ nightly-release:
+ steps:
+ - script:
+ title: Install Dependencies
+ inputs:
+ - content: |-
+ #!/bin/bash
+ set -eu -o pipefail
+ brew install cmake
+ - is_debug: 'yes'
+ - script:
+ title: Configure AWS-CLI
+ inputs:
+ - content: |-
+ #!/bin/bash
+ apt-get install -y python-pip python-dev build-essential
+ pip install awscli
+ - script:
+ title: Build package
+ inputs:
+ - content: |-
+ #!/bin/bash
+ set -eu -o pipefail
+ export BUILDTYPE=Release
+ export BUILD_DEVICE=true
+ export FORMAT=dynamic
+ make ipackage-strip
+ CLOUDWATCH=true platform/ios/scripts/metrics.sh
+ - is_debug: 'yes'
diff --git a/platform/ios/config.cmake b/platform/ios/config.cmake
index 0813d0338f..12db02921c 100644
--- a/platform/ios/config.cmake
+++ b/platform/ios/config.cmake
@@ -1,9 +1,12 @@
add_definitions(-DMBGL_USE_GLES2=1)
+mason_use(icu VERSION 58.1)
+
macro(mbgl_platform_core)
set_xcode_property(mbgl-core IPHONEOS_DEPLOYMENT_TARGET "8.0")
set_xcode_property(mbgl-core ENABLE_BITCODE "YES")
set_xcode_property(mbgl-core BITCODE_GENERATION_MODE bitcode)
+ set_xcode_property(mbgl-core ONLY_ACTIVE_ARCH $<$<CONFIG:Debug>:YES>)
target_sources(mbgl-core
# Loop
@@ -18,6 +21,10 @@ macro(mbgl_platform_core)
PRIVATE platform/default/local_file_source.cpp
PRIVATE platform/default/online_file_source.cpp
+ # Default styles
+ PRIVATE platform/default/mbgl/util/default_styles.hpp
+ PRIVATE platform/default/mbgl/util/default_styles.cpp
+
# Offline
PRIVATE platform/default/mbgl/storage/offline.cpp
PRIVATE platform/default/mbgl/storage/offline_database.cpp
@@ -28,25 +35,32 @@ macro(mbgl_platform_core)
PRIVATE platform/default/sqlite3.hpp
# Misc
- PRIVATE platform/darwin/src/log_nslog.mm
+ PRIVATE platform/darwin/mbgl/storage/reachability.h
+ PRIVATE platform/darwin/mbgl/storage/reachability.m
+ PRIVATE platform/darwin/src/logging_nslog.mm
PRIVATE platform/darwin/src/nsthread.mm
- PRIVATE platform/darwin/src/reachability.m
PRIVATE platform/darwin/src/string_nsstring.mm
+ PRIVATE platform/default/bidi.cpp
# Image handling
PRIVATE platform/darwin/src/image.mm
# Headless view
+ PRIVATE platform/default/mbgl/gl/headless_backend.cpp
+ PRIVATE platform/default/mbgl/gl/headless_backend.hpp
PRIVATE platform/darwin/src/headless_backend_eagl.mm
- PRIVATE platform/default/headless_backend.cpp
- PRIVATE platform/default/headless_display.cpp
- PRIVATE platform/default/offscreen_view.cpp
+ PRIVATE platform/default/mbgl/gl/headless_display.cpp
+ PRIVATE platform/default/mbgl/gl/headless_display.hpp
+ PRIVATE platform/default/mbgl/gl/offscreen_view.cpp
+ PRIVATE platform/default/mbgl/gl/offscreen_view.hpp
# Thread pool
- PRIVATE platform/default/thread_pool.cpp
+ PRIVATE platform/default/mbgl/util/default_thread_pool.cpp
+ PRIVATE platform/default/mbgl/util/default_thread_pool.cpp
)
target_add_mason_package(mbgl-core PUBLIC geojson)
+ target_add_mason_package(mbgl-core PUBLIC icu)
target_compile_options(mbgl-core
PRIVATE -fobjc-arc
@@ -60,7 +74,8 @@ macro(mbgl_platform_core)
)
target_include_directories(mbgl-core
- PRIVATE platform/default
+ PUBLIC platform/darwin
+ PUBLIC platform/default
)
target_link_libraries(mbgl-core
diff --git a/platform/ios/framework/Settings.bundle/zh-Hans.lproj/Root.strings b/platform/ios/framework/Settings.bundle/zh-Hans.lproj/Root.strings
new file mode 100644
index 0000000000..3cfb1a4bad
--- /dev/null
+++ b/platform/ios/framework/Settings.bundle/zh-Hans.lproj/Root.strings
@@ -0,0 +1,3 @@
+"TELEMETRY_GROUP_TITLE" = "隐私设置";
+"TELEMETRY_SWITCH_TITLE" = "Mapbox传感数据";
+"TELEMETRY_GROUP_FOOTER" = "此设置允许应用将用户位置和数据以匿名的方式分享给Mapbox。";
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index 892dbdd39f..42ae50e942 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -163,6 +163,9 @@
40F887711D7A1E59008ECB67 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */; };
40FDA76B1CCAAA6800442548 /* MBXAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */; };
554180421D2E97DE00012372 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 554180411D2E97DE00012372 /* OpenGLES.framework */; };
+ 556660CA1E1BF3A900E2C41B /* MGLFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 556660C91E1BF3A900E2C41B /* MGLFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 556660D81E1D085500E2C41B /* MGLVersionNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = 556660D71E1D085500E2C41B /* MGLVersionNumber.m */; };
+ 556660DB1E1D8E8D00E2C41B /* MGLFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 556660C91E1BF3A900E2C41B /* MGLFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; };
55D8C9961D0F18CE00F42F10 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D8C9951D0F18CE00F42F10 /* libsqlite3.tbd */; };
6407D6701E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */; };
7E016D7E1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E016D7C1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h */; };
@@ -510,6 +513,9 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 20DABE861DF78148007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Foundation.strings"; sourceTree = "<group>"; };
+ 20DABE881DF78148007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
+ 20DABE8A1DF78149007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Root.strings"; sourceTree = "<group>"; };
30E578111DAA7D690050F07E /* UIImage+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage+MGLAdditions.h"; path = "src/UIImage+MGLAdditions.h"; sourceTree = SOURCE_ROOT; };
30E578121DAA7D690050F07E /* UIImage+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "UIImage+MGLAdditions.mm"; path = "src/UIImage+MGLAdditions.mm"; sourceTree = SOURCE_ROOT; };
350098B91D480108004B2AF0 /* MGLVectorSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorSource.h; sourceTree = "<group>"; };
@@ -606,6 +612,8 @@
40FDA7691CCAAA6800442548 /* MBXAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXAnnotationView.h; sourceTree = "<group>"; };
40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXAnnotationView.m; sourceTree = "<group>"; };
554180411D2E97DE00012372 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
+ 556660C91E1BF3A900E2C41B /* MGLFoundation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLFoundation.h; sourceTree = "<group>"; };
+ 556660D71E1D085500E2C41B /* MGLVersionNumber.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLVersionNumber.m; path = ../../darwin/test/MGLVersionNumber.m; sourceTree = "<group>"; };
55D8C9941D0F133500F42F10 /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = config.xcconfig; path = ../../build/ios/config.xcconfig; sourceTree = "<group>"; };
55D8C9951D0F18CE00F42F10 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MGLDocumentationExampleTests.swift; path = ../../darwin/test/MGLDocumentationExampleTests.swift; sourceTree = "<group>"; };
@@ -1100,6 +1108,7 @@
DA2E885F1CC0382C00F24E7B /* MGLOfflineStorageTests.m */,
35B8E08B1D6C8B5100E768D2 /* MGLPredicateTests.mm */,
DA2E88601CC0382C00F24E7B /* MGLStyleTests.mm */,
+ 556660D71E1D085500E2C41B /* MGLVersionNumber.m */,
DA2E88551CC036F400F24E7B /* Info.plist */,
DA2784FB1DF02FF4001D5B8D /* Media.xcassets */,
DA35D0871E1A6309007DED41 /* one-liner.json */,
@@ -1139,6 +1148,7 @@
DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */,
DAF0D8171DFE6B2800B28378 /* MGLAttributionInfo_Private.h */,
DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */,
+ 556660C91E1BF3A900E2C41B /* MGLFoundation.h */,
DA8847E21CBAFA5100AB86E3 /* MGLMapCamera.h */,
DA8848031CBAFA6200AB86E3 /* MGLMapCamera.mm */,
DD0902A41DB18F1B00C5BDCE /* MGLNetworkConfiguration.h */,
@@ -1444,6 +1454,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ 556660DB1E1D8E8D00E2C41B /* MGLFoundation.h in Headers */,
35D13AC31D3D19DD00AFB4E0 /* MGLFillStyleLayer.h in Headers */,
DA88483A1CBAFB8500AB86E3 /* MGLAnnotationImage.h in Headers */,
DA35A2BB1CCA9A6900E826B2 /* MGLClockDirectionFormatter.h in Headers */,
@@ -1557,6 +1568,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ 556660CA1E1BF3A900E2C41B /* MGLFoundation.h in Headers */,
35B82BF91D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h in Headers */,
DA35A2CA1CCAAAD200E826B2 /* NSValue+MGLAdditions.h in Headers */,
350098BC1D480108004B2AF0 /* MGLVectorSource.h in Headers */,
@@ -1804,6 +1816,7 @@
knownRegions = (
en,
Base,
+ "zh-Hans",
);
mainGroup = DA1DC9411CB6C1C2006E619F;
productRefGroup = DA1DC94B1CB6C1C2006E619F /* Products */;
@@ -1969,6 +1982,7 @@
353D23961D0B0DFE002BE09D /* MGLAnnotationViewTests.m in Sources */,
35E208A71D24210F00EC9A46 /* MGLNSDataAdditionsTests.m in Sources */,
DA0CD5901CF56F6A00A5F5A5 /* MGLFeatureTests.mm in Sources */,
+ 556660D81E1D085500E2C41B /* MGLVersionNumber.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2173,6 +2187,7 @@
isa = PBXVariantGroup;
children = (
DA25D5C51CCDA06800607828 /* Base */,
+ 20DABE8A1DF78149007AC5FF /* zh-Hans */,
);
name = Root.strings;
sourceTree = "<group>";
@@ -2181,6 +2196,7 @@
isa = PBXVariantGroup;
children = (
DA8933A01CCC951200E68420 /* Base */,
+ 20DABE881DF78148007AC5FF /* zh-Hans */,
);
name = Localizable.strings;
sourceTree = "<group>";
@@ -2189,6 +2205,7 @@
isa = PBXVariantGroup;
children = (
DA8933BB1CCD2CA100E68420 /* Base */,
+ 20DABE861DF78148007AC5FF /* zh-Hans */,
);
name = Foundation.strings;
sourceTree = "<group>";
@@ -2224,6 +2241,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "libc++";
@@ -2275,6 +2293,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "libc++";
@@ -2437,7 +2456,7 @@
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
VERSIONING_SYSTEM = "apple-generic";
- VERSION_INFO_PREFIX = "";
+ VERSION_INFO_PREFIX = "__attribute__((visibility (\"default\"))) ";
};
name = Debug;
};
@@ -2471,7 +2490,7 @@
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
VERSIONING_SYSTEM = "apple-generic";
- VERSION_INFO_PREFIX = "";
+ VERSION_INFO_PREFIX = "__attribute__((visibility (\"default\"))) ";
};
name = Release;
};
@@ -2519,6 +2538,7 @@
PRODUCT_NAME = Mapbox;
PUBLIC_HEADERS_FOLDER_PATH = Headers;
SKIP_INSTALL = YES;
+ VERSION_INFO_PREFIX = "__attribute__((visibility (\"default\"))) ";
};
name = Debug;
};
@@ -2544,6 +2564,7 @@
PRODUCT_NAME = Mapbox;
PUBLIC_HEADERS_FOLDER_PATH = Headers;
SKIP_INSTALL = YES;
+ VERSION_INFO_PREFIX = "__attribute__((visibility (\"default\"))) ";
};
name = Release;
};
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
index cb3d7b0242..437f000a3c 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0800"
+ LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme
index 5f80514b41..0a12923924 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0800"
+ LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic+static.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic+static.xcscheme
index 67f630ea41..2bba3a3e05 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic+static.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic+static.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0800"
+ LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme
index ae4ebcc5d4..31c86be795 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0800"
+ LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme
index 05d05b2ec9..a299ab49b1 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0800"
+ LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme
index f56be478f7..9bfc8aac36 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0800"
+ LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
diff --git a/platform/ios/resources/zh-Hans.lproj/Localizable.strings b/platform/ios/resources/zh-Hans.lproj/Localizable.strings
new file mode 100644
index 0000000000..087a09dbb8
--- /dev/null
+++ b/platform/ios/resources/zh-Hans.lproj/Localizable.strings
@@ -0,0 +1,84 @@
+/* Accessibility hint */
+"ANNOTATION_A11Y_HINT" = "显示信息";
+
+/* No comment provided by engineer. */
+"API_CLIENT_400_DESC" = "The session data task failed. Original request was: %@";
+
+/* No comment provided by engineer. */
+"API_CLIENT_400_REASON" = "The status code was %ld";
+
+/* No comment provided by engineer. */
+"CANCEL" = "取消";
+
+/* Accessibility hint */
+"COMPASS_A11Y_HINT" = "旋转地图使正北朝上";
+
+/* Accessibility label */
+"COMPASS_A11Y_LABEL" = "指南针";
+
+/* Compass abbreviation for north */
+"COMPASS_NORTH" = "北";
+
+/* Copyright notice in attribution sheet */
+"COPY_MAPBOX" = "© Mapbox";
+
+/* Copyright notice in attribution sheet */
+"COPY_OSM" = "© OpenStreetMap";
+
+/* Instructions in Interface Builder designable; {key}, {plist file name} */
+"DESIGNABLE" = "在%2$@中将你的access token设为%1$@可在这里显示Mapbox上的地图\n\n更多说明请见";
+
+/* Setup documentation URL display string; keep as short as possible */
+"FIRST_STEPS_URL" = "mapbox.com/help/first-steps-ios-sdk";
+
+/* Accessibility hint */
+"INFO_A11Y_HINT" = "显示致谢、用户反馈及更多";
+
+/* Accessibility label */
+"INFO_A11Y_LABEL" = "关于这个地图";
+
+/* Accessibility label */
+"LOGO_A11Y_LABEL" = "Mapbox";
+
+/* Accessibility label */
+"MAP_A11Y_LABEL" = "地图";
+
+/* Map accessibility value */
+"MAP_A11Y_VALUE" = "地图缩放%1$d倍\n有%2$ld处标记可见";
+
+/* Action in attribution sheet */
+"MAP_FEEDBACK" = "改进地图";
+
+/* Action sheet title */
+"SDK_NAME" = "Mapbox iOS SDK";
+
+/* Telemetry prompt message */
+"TELEMETRY_DISABLED_MSG" = "你可以提供匿名数据来帮助OpenStreetMap和Mapbox的地图变得更好。";
+
+/* Telemetry prompt button */
+"TELEMETRY_DISABLED_OFF" = "暂不参与";
+
+/* Telemetry prompt button */
+"TELEMETRY_DISABLED_ON" = "我要参与";
+
+/* Telemetry prompt message */
+"TELEMETRY_ENABLED_MSG" = "你的匿名数据在帮助OpenStreetMap和Mapbox的地图变得更好。";
+
+/* Telemetry prompt button */
+"TELEMETRY_ENABLED_OFF" = "不再参与";
+
+/* Telemetry prompt button */
+"TELEMETRY_ENABLED_ON" = "继续参与";
+
+/* Telemetry prompt button */
+"TELEMETRY_MORE" = "详细信息";
+
+/* Action in attribution sheet */
+"TELEMETRY_NAME" = "Mapbox传感数据";
+
+/* Telemetry prompt title */
+"TELEMETRY_TITLE" = "让Mapbox地图变得更好";
+
+/* Default user location annotation title */
+"USER_DOT_TITLE" = "你在这里";
+
diff --git a/platform/ios/scripts/metrics.sh b/platform/ios/scripts/metrics.sh
new file mode 100755
index 0000000000..c45beb3a11
--- /dev/null
+++ b/platform/ios/scripts/metrics.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -e
+set -o pipefail
+
+# Generate stripped versions for every architecture
+xcrun bitcode_strip build/ios/pkg/dynamic/Mapbox.framework/Mapbox -r -o build/ios/pkg/dynamic/Mapbox-stripped
+lipo build/ios/pkg/dynamic/Mapbox-stripped -extract armv7 -output build/ios/pkg/dynamic/Mapbox-stripped-armv7
+lipo build/ios/pkg/dynamic/Mapbox-stripped -extract arm64 -output build/ios/pkg/dynamic/Mapbox-stripped-arm64
+lipo build/ios/pkg/dynamic/Mapbox-stripped -extract i386 -output build/ios/pkg/dynamic/Mapbox-stripped-i386
+lipo build/ios/pkg/dynamic/Mapbox-stripped -extract x86_64 -output build/ios/pkg/dynamic/Mapbox-stripped-x86_64
+
+# Track individual architectures
+scripts/log_binary_size.sh "build/ios/pkg/dynamic/Mapbox-stripped-armv7" "Platform=iOS,Arch=armv7"
+scripts/log_binary_size.sh "build/ios/pkg/dynamic/Mapbox-stripped-arm64" "Platform=iOS,Arch=arm64"
+scripts/log_binary_size.sh "build/ios/pkg/dynamic/Mapbox-stripped-i386" "Platform=iOS,Arch=i386"
+scripts/log_binary_size.sh "build/ios/pkg/dynamic/Mapbox-stripped-x86_64" "Platform=iOS,Arch=x86_64"
+
+# Track overall library size
+scripts/log_binary_size.sh "build/ios/pkg/dynamic/Mapbox-stripped" "Platform=iOS,Arch=Dynamic"
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index ba40997bc3..c211d4419b 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -1,20 +1,21 @@
#import "MGLMapView_Private.h"
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/gl/extension.hpp>
#include <mbgl/gl/context.hpp>
#import <GLKit/GLKit.h>
#import <OpenGLES/EAGL.h>
-#include <mbgl/mbgl.hpp>
+#include <mbgl/map/map.hpp>
+#include <mbgl/map/view.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/map/mode.hpp>
-#include <mbgl/platform/platform.hpp>
-#include <mbgl/platform/darwin/reachability.h>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/util/platform.hpp>
+#include <mbgl/storage/reachability.h>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/style/transition_options.hpp>
@@ -422,12 +423,10 @@ public:
[[NSFileManager defaultManager] removeItemAtPath:fileCachePath error:NULL];
// setup mbgl map
- const std::array<uint16_t, 2> size = {{ static_cast<uint16_t>(self.bounds.size.width),
- static_cast<uint16_t>(self.bounds.size.height) }};
mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
_mbglThreadPool = new mbgl::ThreadPool(4);
- _mbglMap = new mbgl::Map(*_mbglView, size, scaleFactor, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
+ _mbglMap = new mbgl::Map(*_mbglView, self.size, scaleFactor, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
[self validateTileCacheSize];
// start paused if in IB
@@ -570,6 +569,18 @@ public:
}
}
+- (mbgl::Size)size
+{
+ return { static_cast<uint32_t>(self.bounds.size.width),
+ static_cast<uint32_t>(self.bounds.size.height) };
+}
+
+- (mbgl::Size)framebufferSize
+{
+ return { static_cast<uint32_t>(self.glView.drawableWidth),
+ static_cast<uint32_t>(self.glView.drawableHeight) };
+}
+
- (void)createGLView
{
if (_context) return;
@@ -878,10 +889,8 @@ public:
[self adjustContentInset];
- if ( ! _isTargetingInterfaceBuilder)
- {
- _mbglMap->setSize({{ static_cast<uint16_t>(self.bounds.size.width),
- static_cast<uint16_t>(self.bounds.size.height) }});
+ if (!_isTargetingInterfaceBuilder) {
+ _mbglMap->setSize([self size]);
}
if (self.attributionSheet.visible)
@@ -5132,13 +5141,11 @@ public:
class MBGLView : public mbgl::View, public mbgl::Backend
{
public:
- MBGLView(MGLMapView* nativeView_)
- : nativeView(nativeView_) {
+ MBGLView(MGLMapView* nativeView_) : nativeView(nativeView_) {
}
mbgl::gl::value::Viewport::Type getViewport() const {
- return { 0, 0, static_cast<uint16_t>(nativeView.glView.drawableWidth),
- static_cast<uint16_t>(nativeView.glView.drawableHeight) };
+ return { 0, 0, nativeView.framebufferSize };
}
/// This function is called before we start rendering, when iOS invokes our rendering method.
@@ -5148,6 +5155,7 @@ public:
// We are using 0 as the placeholder value for the GLKView's framebuffer.
getContext().bindFramebuffer.setCurrentValue(0);
getContext().viewport.setCurrentValue(getViewport());
+ assert(mbgl::gl::value::Viewport::Get() == getContext().viewport.getCurrentValue());
}
void bind() override {
diff --git a/platform/ios/src/MGLMapboxEvents.m b/platform/ios/src/MGLMapboxEvents.m
index 90123fbb00..744b80047b 100644
--- a/platform/ios/src/MGLMapboxEvents.m
+++ b/platform/ios/src/MGLMapboxEvents.m
@@ -7,7 +7,7 @@
#import "MGLAPIClient.h"
#import "MGLLocationManager.h"
-#include <mbgl/platform/darwin/reachability.h>
+#include <mbgl/storage/reachability.h>
#include <sys/sysctl.h>
// Event types
diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h
index c0d85d4b9a..37c649781e 100644
--- a/platform/ios/src/Mapbox.h
+++ b/platform/ios/src/Mapbox.h
@@ -1,10 +1,12 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
+
/// Project version number for Mapbox.
-FOUNDATION_EXPORT double MapboxVersionNumber;
+FOUNDATION_EXPORT MGL_EXPORT double MapboxVersionNumber;
/// Project version string for Mapbox.
-FOUNDATION_EXPORT const unsigned char MapboxVersionString[];
+FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLAnnotationView.h"
#import "MGLAccountManager.h"
diff --git a/platform/ios/src/UIImage+MGLAdditions.mm b/platform/ios/src/UIImage+MGLAdditions.mm
index e4d072e136..7b5737f5e4 100644
--- a/platform/ios/src/UIImage+MGLAdditions.mm
+++ b/platform/ios/src/UIImage+MGLAdditions.mm
@@ -22,7 +22,7 @@
size_t width = CGImageGetWidth(cgImage);
size_t height = CGImageGetHeight(cgImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- mbgl::PremultipliedImage cPremultipliedImage(width, height);
+ mbgl::PremultipliedImage cPremultipliedImage({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
size_t bytesPerPixel = 4;
size_t bytesPerRow = bytesPerPixel * width;
size_t bitsPerComponent = 8;
diff --git a/platform/ios/test/MGLSourceTests.m b/platform/ios/test/MGLSourceTests.m
new file mode 100644
index 0000000000..90ec4e3a0b
--- /dev/null
+++ b/platform/ios/test/MGLSourceTests.m
@@ -0,0 +1,24 @@
+#import "MGLMapViewTests.h"
+
+@interface MGLSourceTests : MGLMapViewTests
+
+@end
+
+@implementation MGLSourceTests
+
+- (void)testDuplicateSources {
+ MGLVectorSource *source1 = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" URL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
+ MGLVectorSource *source2 = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" URL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
+
+ [self.mapView.style addSource: source1];
+
+ @try {
+ [self.mapView.style addSource: source2];
+ XCTFail(@"Should not have reached this point");
+ }
+ @catch (NSException *e) {
+ XCTAssertNotNil(e, @"Should have thrown an exception");
+ }
+}
+
+@end
diff --git a/platform/ios/toolchain.cmake b/platform/ios/toolchain.cmake
index 60dbac07c7..512b46b6d9 100644
--- a/platform/ios/toolchain.cmake
+++ b/platform/ios/toolchain.cmake
@@ -113,13 +113,6 @@ set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-
-# This little macro lets you set any XCode specific property
-macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
- set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
-endmacro (set_xcode_property)
-
-
# This macro lets you find executable programs on the host system
macro (find_host_package)
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
diff --git a/platform/ios/uitest/KIF b/platform/ios/uitest/KIF
-Subproject bcb58d0419cfaefe286f3df1c8618bac43b4592
+Subproject 973a4cb653b54c3e8b2c0681f4097568ff0ac34
diff --git a/platform/ios/uitest/OHHTTPStubs b/platform/ios/uitest/OHHTTPStubs
-Subproject e3cd0173c459b8cd43f202fe8816f1675916717
+Subproject deed01a1592210a4c37f3f5c5f2b32fe0e41c60
diff --git a/platform/linux/README.md b/platform/linux/README.md
index f7dc2dbec6..b6a3b9a446 100644
--- a/platform/linux/README.md
+++ b/platform/linux/README.md
@@ -22,6 +22,12 @@ Ensure you have git and other build essentials:
libcurl4-openssl-dev libpng-dev libsqlite3-dev \
libllvm3.4
+Ensure you have cmake 3.x:
+
+ sudo add-apt-repository --yes ppa:george-edison55/cmake-3.x
+ sudo apt-get update
+ sudo apt-get install cmake cmake-data
+
Install glfw3 dependencies:
sudo apt-get install libxi-dev libglu1-mesa-dev x11proto-randr-dev \
diff --git a/platform/linux/config.cmake b/platform/linux/config.cmake
index 8acb6e7e14..bad3751b06 100644
--- a/platform/linux/config.cmake
+++ b/platform/linux/config.cmake
@@ -1,6 +1,8 @@
mason_use(glfw VERSION 3.2.1)
-mason_use(mesa VERSION 13.0.0${MASON_CXXABI_SUFFIX})
-mason_use(boost_libprogram_options VERSION 1.60.0)
+if(IS_CI_BUILD AND NOT WITH_EGL)
+ mason_use(mesa VERSION 13.0.0${MASON_MESA_SUFFIX})
+endif()
+mason_use(boost_libprogram_options VERSION 1.62.0${MASON_CXXABI_SUFFIX})
mason_use(sqlite VERSION 3.14.2)
mason_use(libuv VERSION 1.9.1)
mason_use(nunicode VERSION 1.7.1)
@@ -9,35 +11,43 @@ mason_use(libjpeg-turbo VERSION 1.5.0)
mason_use(webp VERSION 0.5.1)
mason_use(gtest VERSION 1.7.0${MASON_CXXABI_SUFFIX})
mason_use(benchmark VERSION 1.0.0)
+mason_use(icu VERSION 58.1)
include(cmake/loop-uv.cmake)
-macro(use_glx_backend _TARGET)
- target_sources(${_TARGET}
- PRIVATE platform/default/headless_backend_glx.cpp
- )
-
- target_link_libraries(${_TARGET}
- PUBLIC -lGL
- PUBLIC -lX11
- )
-endmacro()
-
-macro(use_osmesa_backend _TARGET)
- target_sources(${_TARGET}
- PRIVATE platform/default/headless_backend_osmesa.cpp
- )
-
- target_add_mason_package(${_TARGET}
- PUBLIC mesa
- )
-endmacro()
-
macro(mbgl_platform_core)
- if (WITH_OSMESA)
- use_osmesa_backend(mbgl-core)
+ if(WITH_OSMESA)
+ target_sources(mbgl-core
+ PRIVATE platform/default/headless_backend_osmesa.cpp
+ PRIVATE platform/default/mbgl/gl/headless_display.cpp
+ )
+ target_add_mason_package(mbgl-core PUBLIC mesa)
+ elseif(WITH_EGL)
+ target_sources(mbgl-core
+ PRIVATE platform/linux/src/headless_backend_egl.cpp
+ PRIVATE platform/linux/src/headless_display_egl.cpp
+ )
+ # TODO: Provide surface-less EGL mesa for CI builds.
+ # https://github.com/mapbox/mapbox-gl-native/issues/7020
+ target_link_libraries(mbgl-core
+ PUBLIC -lGLESv2
+ PUBLIC -lEGL
+ PUBLIC -lgbm
+ )
else()
- use_glx_backend(mbgl-core)
+ target_sources(mbgl-core
+ PRIVATE platform/linux/src/headless_backend_glx.cpp
+ PRIVATE platform/linux/src/headless_display_glx.cpp
+ )
+ if (IS_CI_BUILD)
+ target_add_mason_package(mbgl-core PUBLIC mesa)
+ target_link_libraries(mbgl-core PUBLIC -lX11)
+ else()
+ target_link_libraries(mbgl-core
+ PUBLIC -lGL
+ PUBLIC -lX11
+ )
+ endif()
endif()
target_sources(mbgl-core
@@ -58,9 +68,10 @@ macro(mbgl_platform_core)
PRIVATE platform/default/sqlite3.hpp
# Misc
- PRIVATE platform/default/log_stderr.cpp
+ PRIVATE platform/default/logging_stderr.cpp
PRIVATE platform/default/string_stdlib.cpp
PRIVATE platform/default/thread.cpp
+ PRIVATE platform/default/bidi.cpp
# Image handling
PRIVATE platform/default/image.cpp
@@ -69,12 +80,15 @@ macro(mbgl_platform_core)
PRIVATE platform/default/webp_reader.cpp
# Headless view
- PRIVATE platform/default/headless_backend.cpp
- PRIVATE platform/default/headless_display.cpp
- PRIVATE platform/default/offscreen_view.cpp
+ PRIVATE platform/default/mbgl/gl/headless_backend.cpp
+ PRIVATE platform/default/mbgl/gl/headless_backend.hpp
+ PRIVATE platform/default/mbgl/gl/headless_display.hpp
+ PRIVATE platform/default/mbgl/gl/offscreen_view.cpp
+ PRIVATE platform/default/mbgl/gl/offscreen_view.hpp
# Thread pool
- PRIVATE platform/default/thread_pool.cpp
+ PRIVATE platform/default/mbgl/util/default_thread_pool.cpp
+ PRIVATE platform/default/mbgl/util/default_thread_pool.cpp
)
target_include_directories(mbgl-core
@@ -86,6 +100,7 @@ macro(mbgl_platform_core)
target_add_mason_package(mbgl-core PUBLIC libpng)
target_add_mason_package(mbgl-core PUBLIC libjpeg-turbo)
target_add_mason_package(mbgl-core PUBLIC webp)
+ target_add_mason_package(mbgl-core PUBLIC icu)
target_link_libraries(mbgl-core
PUBLIC -lz
diff --git a/platform/linux/scripts/after_success.sh b/platform/linux/scripts/after_success.sh
new file mode 100755
index 0000000000..3531e3fb74
--- /dev/null
+++ b/platform/linux/scripts/after_success.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+set -e
+set -o pipefail
+
+if [ "${TRAVIS_PULL_REQUEST_BRANCH:-${TRAVIS_BRANCH}}" = "master" ] && [ "${BUILDTYPE}" = "Release" ]; then
+ CLOUDWATCH=true platform/linux/scripts/metrics.sh
+else
+ echo "Not logging binary size for branch or Debug build"
+fi
diff --git a/platform/linux/scripts/metrics.sh b/platform/linux/scripts/metrics.sh
new file mode 100755
index 0000000000..82dcf98d5c
--- /dev/null
+++ b/platform/linux/scripts/metrics.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+set -e
+set -o pipefail
+
+# Generate stripped version
+ARCH=$(uname -m)
+RENDER=build/linux-${ARCH}/Release/mbgl-render
+strip -s -x "${RENDER}" -o "${RENDER}-stripped"
+
+# Track individual architecture
+scripts/log_binary_size.sh "${RENDER}-stripped" "Platform=Linux,Compiler=${_CC},Arch=${ARCH}"
diff --git a/platform/linux/src/headless_backend_egl.cpp b/platform/linux/src/headless_backend_egl.cpp
new file mode 100644
index 0000000000..87e7c1d0ed
--- /dev/null
+++ b/platform/linux/src/headless_backend_egl.cpp
@@ -0,0 +1,103 @@
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/headless_display.hpp>
+
+#include <mbgl/util/logging.hpp>
+
+#include <EGL/egl.h>
+
+#include <cassert>
+
+namespace mbgl {
+
+struct EGLImpl : public HeadlessBackend::Impl {
+ EGLImpl(EGLContext glContext_, EGLDisplay display_, EGLConfig config_)
+ : glContext(glContext_),
+ display(display_),
+ config(config_) {
+#if __ANDROID__
+ // Create a pixel buffer surface (in conjunction with EGL_SURFACE_TYPE, EGL_PBUFFER_BIT).
+ const EGLint surfAttribs[] = {
+ EGL_WIDTH, 512,
+ EGL_HEIGHT, 512,
+ EGL_LARGEST_PBUFFER, EGL_TRUE,
+ EGL_NONE
+ };
+
+ glSurface = eglCreatePbufferSurface(display, config, surfAttribs);
+ if (glSurface == EGL_NO_SURFACE) {
+ throw std::runtime_error("Could not create surface: " + std::to_string(eglGetError()));
+ }
+#endif // __ANDROID__
+ }
+
+ ~EGLImpl() {
+ if (glContext != eglGetCurrentContext()) {
+ activateContext();
+ }
+ if (!eglDestroyContext(display, glContext)) {
+ throw std::runtime_error("Failed to destroy EGL context.\n");
+ }
+ if (glSurface != EGL_NO_SURFACE) {
+ if (!eglDestroySurface(display, glSurface)) {
+ throw std::runtime_error("Failed to destroy EGL context.\n");
+ }
+ glSurface = EGL_NO_SURFACE;
+ }
+ }
+
+ void activateContext() final {
+ if (!eglMakeCurrent(display, glSurface, glSurface, glContext)) {
+ throw std::runtime_error("Switching OpenGL context failed.\n");
+ }
+ }
+
+ void deactivateContext() final {
+ if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
+ throw std::runtime_error("Removing OpenGL context failed.\n");
+ }
+ }
+
+ EGLContext glContext = EGL_NO_CONTEXT;
+ EGLDisplay display = EGL_NO_DISPLAY;
+ EGLConfig config = 0;
+ EGLSurface glSurface = EGL_NO_SURFACE;
+};
+
+gl::glProc HeadlessBackend::initializeExtension(const char* name) {
+ return eglGetProcAddress(name);
+}
+
+bool HeadlessBackend::hasDisplay() {
+ if (!display) {
+ display.reset(new HeadlessDisplay);
+ }
+ return bool(display);
+};
+
+void HeadlessBackend::createContext() {
+ assert(!hasContext());
+ assert(hasDisplay());
+
+ EGLDisplay display_ = display->attribute<EGLDisplay>();
+ EGLConfig& config = display->attribute<EGLConfig&>();
+
+ // EGL initializes the context client version to 1 by default. We want to
+ // use OpenGL ES 2.0 which has the ability to create shader and program
+ // objects and also to write vertex and fragment shaders in the OpenGL ES
+ // Shading Language.
+ const EGLint attribs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ EGLContext glContext = eglCreateContext(display_, config, EGL_NO_CONTEXT, attribs);
+ if (glContext == EGL_NO_CONTEXT) {
+ mbgl::Log::Error(mbgl::Event::OpenGL, "eglCreateContext() returned error 0x%04x",
+ eglGetError());
+ throw std::runtime_error("Error creating the EGL context object.\n");
+ }
+
+ impl.reset(new EGLImpl(glContext, display_, config));
+}
+
+} // namespace mbgl
diff --git a/platform/linux/src/headless_backend_glx.cpp b/platform/linux/src/headless_backend_glx.cpp
new file mode 100644
index 0000000000..5791f1892f
--- /dev/null
+++ b/platform/linux/src/headless_backend_glx.cpp
@@ -0,0 +1,87 @@
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/headless_display.hpp>
+
+#include <mbgl/util/logging.hpp>
+
+#include <cassert>
+
+#include <GL/glx.h>
+
+namespace mbgl {
+
+struct GLXImpl : public HeadlessBackend::Impl {
+ GLXImpl(GLXContext glContext_, GLXPbuffer glxPbuffer_, Display* xDisplay_, GLXFBConfig* fbConfigs_)
+ : glContext(glContext_),
+ glxPbuffer(glxPbuffer_),
+ xDisplay(xDisplay_),
+ fbConfigs(fbConfigs_) {
+ }
+
+ ~GLXImpl() {
+ if (glxPbuffer) {
+ glXDestroyPbuffer(xDisplay, glxPbuffer);
+ }
+ glXDestroyContext(xDisplay, glContext);
+ }
+
+ void activateContext() final {
+ if (!glXMakeContextCurrent(xDisplay, glxPbuffer, glxPbuffer, glContext)) {
+ throw std::runtime_error("Switching OpenGL context failed.\n");
+ }
+ }
+
+ void deactivateContext() final {
+ if (!glXMakeContextCurrent(xDisplay, 0, 0, nullptr)) {
+ throw std::runtime_error("Removing OpenGL context failed.\n");
+ }
+ }
+
+ GLXContext glContext = nullptr;
+ GLXPbuffer glxPbuffer = 0;
+
+ // Needed for ImplDeleter.
+ Display* xDisplay = nullptr;
+ GLXFBConfig* fbConfigs = nullptr;
+};
+
+gl::glProc HeadlessBackend::initializeExtension(const char* name) {
+ return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
+}
+
+bool HeadlessBackend::hasDisplay() {
+ if (!display) {
+ display.reset(new HeadlessDisplay);
+ }
+ return bool(display);
+};
+
+void HeadlessBackend::createContext() {
+ assert(!hasContext());
+
+ Display* xDisplay = display->attribute<Display*>();
+ GLXFBConfig* fbConfigs = display->attribute<GLXFBConfig*>();
+
+ // Try to create a legacy context.
+ GLXContext glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, None, True);
+ if (glContext && !glXIsDirect(xDisplay, glContext)) {
+ Log::Error(Event::OpenGL, "failed to create direct OpenGL Legacy context");
+ glXDestroyContext(xDisplay, glContext);
+ glContext = nullptr;
+ }
+ if (glContext == nullptr) {
+ throw std::runtime_error("Error creating GL context object.");
+ }
+
+ // Create a dummy pbuffer. We will render to framebuffers anyway, but we need a pbuffer to
+ // activate the context.
+ int pbufferAttributes[] = {
+ GLX_PBUFFER_WIDTH, 8,
+ GLX_PBUFFER_HEIGHT, 8,
+ None
+ };
+ GLXPbuffer glxPbuffer = glXCreatePbuffer(xDisplay, fbConfigs[0], pbufferAttributes);
+
+ impl.reset(new GLXImpl(glContext, glxPbuffer, xDisplay, fbConfigs));
+}
+
+} // namespace mbgl
diff --git a/platform/linux/src/headless_display_egl.cpp b/platform/linux/src/headless_display_egl.cpp
new file mode 100644
index 0000000000..eddc05feaf
--- /dev/null
+++ b/platform/linux/src/headless_display_egl.cpp
@@ -0,0 +1,69 @@
+#include <mbgl/gl/headless_display.hpp>
+#include <mbgl/util/logging.hpp>
+#include <mbgl/util/string.hpp>
+
+#include <EGL/egl.h>
+
+namespace mbgl {
+
+class HeadlessDisplay::Impl {
+public:
+ Impl();
+ ~Impl();
+
+ EGLDisplay display = EGL_NO_DISPLAY;
+ EGLConfig config = 0;
+};
+
+HeadlessDisplay::Impl::Impl() {
+ display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (display == EGL_NO_DISPLAY) {
+ throw std::runtime_error("Failed to obtain a valid EGL display.\n");
+ }
+
+ EGLint major, minor, numConfigs;
+ if (!eglInitialize(display, &major, &minor)) {
+ throw std::runtime_error("eglInitialize() failed.\n");
+ }
+
+ if (!eglBindAPI(EGL_OPENGL_ES_API)) {
+ mbgl::Log::Error(mbgl::Event::OpenGL, "eglBindAPI(EGL_OPENGL_ES_API) returned error %d", eglGetError());
+ throw std::runtime_error("eglBindAPI() failed");
+ }
+
+ const EGLint attribs[] = {
+#if __ANDROID__
+ // Android emulator requires a pixel buffer to generate renderable unit
+ // test results.
+ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+#endif // __ANDROID__
+ EGL_NONE
+ };
+
+ if (!eglChooseConfig(display, attribs, &config, 1, &numConfigs) || numConfigs != 1) {
+ throw std::runtime_error("Failed to choose ARGB config.\n");
+ }
+}
+
+HeadlessDisplay::Impl::~Impl() {
+ eglTerminate(display);
+}
+
+template <>
+EGLDisplay HeadlessDisplay::attribute() const {
+ return impl->display;
+}
+
+template <>
+EGLConfig& HeadlessDisplay::attribute() const {
+ return impl->config;
+}
+
+HeadlessDisplay::HeadlessDisplay()
+ : impl(std::make_unique<Impl>()) {
+}
+
+HeadlessDisplay::~HeadlessDisplay() {
+}
+
+} // namespace mbgl
diff --git a/platform/default/headless_display.cpp b/platform/linux/src/headless_display_glx.cpp
index b98aef7903..4275ebb646 100644
--- a/platform/default/headless_display.cpp
+++ b/platform/linux/src/headless_display_glx.cpp
@@ -1,8 +1,6 @@
-#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/gl/headless_display.hpp>
-#if MBGL_USE_GLX
#include <GL/glx.h>
-#endif
#include <cstring>
#include <stdexcept>
@@ -10,27 +8,16 @@
namespace mbgl {
-HeadlessDisplay::HeadlessDisplay() {
-#if MBGL_USE_CGL
- // TODO: test if OpenGL 4.1 with GL_ARB_ES2_compatibility is supported
- // If it is, use kCGLOGLPVersion_3_2_Core and enable that extension.
- CGLPixelFormatAttribute attributes[] = {
- kCGLPFAOpenGLProfile,
- static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_Legacy),
- static_cast<CGLPixelFormatAttribute>(0)
- };
+class HeadlessDisplay::Impl {
+public:
+ Impl();
+ ~Impl();
- GLint num;
- CGLError error = CGLChoosePixelFormat(attributes, &pixelFormat, &num);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Error choosing pixel format:") + CGLErrorString(error) + "\n");
- }
- if (num <= 0) {
- throw std::runtime_error("No pixel formats found.");
- }
-#endif
+ Display* xDisplay = nullptr;
+ GLXFBConfig* fbConfigs = nullptr;
+};
-#if MBGL_USE_GLX
+HeadlessDisplay::Impl::Impl() {
if (!XInitThreads()) {
throw std::runtime_error("Failed to XInitThreads.");
}
@@ -65,18 +52,28 @@ HeadlessDisplay::HeadlessDisplay() {
if (configs <= 0) {
throw std::runtime_error("No Framebuffer configurations.");
}
-#endif
}
-HeadlessDisplay::~HeadlessDisplay() {
-#if MBGL_USE_CGL
- CGLDestroyPixelFormat(pixelFormat);
-#endif
-
-#if MBGL_USE_GLX
+HeadlessDisplay::Impl::~Impl() {
XFree(fbConfigs);
XCloseDisplay(xDisplay);
-#endif
+}
+
+template <>
+Display* HeadlessDisplay::attribute() const {
+ return impl->xDisplay;
+}
+
+template <>
+GLXFBConfig* HeadlessDisplay::attribute() const {
+ return impl->fbConfigs;
+}
+
+HeadlessDisplay::HeadlessDisplay()
+ : impl(std::make_unique<Impl>()) {
+}
+
+HeadlessDisplay::~HeadlessDisplay() {
}
} // namespace mbgl
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index bc15b4667e..fe1a316fab 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog for Mapbox macOS SDK
+## master
+
+* Labels written in Arabic, Hebrew, and other scripts are written right-to-left. Arabic characters are correctly shaped. ([#6984](https://github.com/mapbox/mapbox-gl-native/pull/6984), [#7123](https://github.com/mapbox/mapbox-gl-native/pull/7123))
+* Improved the line wrapping behavior of point-placed labels written in Chinese, Japanese, and Yi. ([#6828](https://github.com/mapbox/mapbox-gl-native/pull/6828))
+* Fixed an issue where translucent point annotations along tile boundaries would be drawn darker than expected. ([#6832](https://github.com/mapbox/mapbox-gl-native/pull/6832))
+* Added a Simplified Chinese localization. ([#7316](https://github.com/mapbox/mapbox-gl-native/pull/7316), [#7503](https://github.com/mapbox/mapbox-gl-native/pull/7503))
+
## 0.3.0
This version of the Mapbox macOS SDK corresponds to version 3.4.0 of the Mapbox iOS SDK. The two SDKs have very similar feature sets. The main differences are the lack of user location tracking and annotation views. Some APIs have been adapted to macOS conventions, particularly the use of NSPopover for callout views.
diff --git a/platform/macos/DEVELOPING.md b/platform/macos/DEVELOPING.md
index 823ad4656b..6737566a5c 100644
--- a/platform/macos/DEVELOPING.md
+++ b/platform/macos/DEVELOPING.md
@@ -54,6 +54,7 @@ To add any Objective-C type, constant, or member to the iOS SDK’s public inter
To add an Objective-C class, protocol, category, typedef, enumeration, or global constant to the macOS SDK’s public interface:
+1. _(Optional.)_ Add the macro `MGL_EXPORT` prior to the declaration for classes and global constants. To use this macro, include `MGLFoundation.h`. You can check whether all public symbols are exported correctly by running `make check-public-symbols`.
1. _(Optional.)_ Add the type or constant’s name to the relevant category in the `custom_categories` section of [the jazzy configuration file](./jazzy.yml). This is required for classes and protocols and also recommended for any other type that is strongly associated with a particular class or protocol. If you leave out this step, the symbol will appear in an “Other” section in the generated HTML documentation’s table of contents.
1. _(Optional.)_ If the symbol would also be publicly exposed in the iOS SDK, consult [the companion iOS document](../ios/DEVELOPING.md#making-a-type-or-constant-public) for further instructions.
diff --git a/platform/macos/bitrise.yml b/platform/macos/bitrise.yml
index 340d72e27c..2de6bce1fc 100644
--- a/platform/macos/bitrise.yml
+++ b/platform/macos/bitrise.yml
@@ -2,6 +2,8 @@ format_version: 1.1.0
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
trigger_map:
+- pattern: nightly-release
+ workflow: nightly-release
- pattern: "*"
is_pull_request_allowed: true
workflow: primary
@@ -78,3 +80,31 @@ workflows:
failed'
- icon_url: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-icon-128.png
- icon_url_on_error: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-error-icon-128.png
+ nightly-release:
+ steps:
+ - script:
+ title: Install Dependencies
+ inputs:
+ - content: |-
+ #!/bin/bash
+ set -eu -o pipefail
+ brew install cmake
+ - is_debug: 'yes'
+ - script:
+ title: Configure AWS-CLI
+ inputs:
+ - content: |-
+ #!/bin/bash
+ apt-get install -y python-pip python-dev build-essential
+ pip install awscli
+ - script:
+ title: Build package
+ inputs:
+ - content: |-
+ #!/bin/bash
+ set -eu -o pipefail
+ export BUILDTYPE=Release
+ export SYMBOLS=NO
+ make xpackage
+ CLOUDWATCH=true platform/macos/scripts/metrics.sh
+ - is_debug: 'yes'
diff --git a/platform/macos/config.cmake b/platform/macos/config.cmake
index 27bf555ec6..2e4b7a01b2 100644
--- a/platform/macos/config.cmake
+++ b/platform/macos/config.cmake
@@ -1,9 +1,10 @@
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.10)
mason_use(glfw VERSION 3.2.1)
-mason_use(boost_libprogram_options VERSION 1.60.0)
+mason_use(boost_libprogram_options VERSION 1.62.0)
mason_use(gtest VERSION 1.7.0${MASON_CXXABI_SUFFIX})
mason_use(benchmark VERSION 1.0.0)
+mason_use(icu VERSION 58.1)
include(cmake/loop-darwin.cmake)
@@ -16,6 +17,10 @@ macro(mbgl_platform_core)
PRIVATE platform/default/local_file_source.cpp
PRIVATE platform/default/online_file_source.cpp
+ # Default styles
+ PRIVATE platform/default/mbgl/util/default_styles.hpp
+ PRIVATE platform/default/mbgl/util/default_styles.cpp
+
# Offline
PRIVATE platform/default/mbgl/storage/offline.cpp
PRIVATE platform/default/mbgl/storage/offline_database.cpp
@@ -26,32 +31,41 @@ macro(mbgl_platform_core)
PRIVATE platform/default/sqlite3.hpp
# Misc
- PRIVATE platform/darwin/src/log_nslog.mm
+ PRIVATE platform/darwin/mbgl/storage/reachability.h
+ PRIVATE platform/darwin/mbgl/storage/reachability.m
+ PRIVATE platform/darwin/src/logging_nslog.mm
PRIVATE platform/darwin/src/nsthread.mm
- PRIVATE platform/darwin/src/reachability.m
PRIVATE platform/darwin/src/string_nsstring.mm
+ PRIVATE platform/default/bidi.cpp
# Image handling
PRIVATE platform/darwin/src/image.mm
# Headless view
+ PRIVATE platform/default/mbgl/gl/headless_backend.cpp
+ PRIVATE platform/default/mbgl/gl/headless_backend.hpp
PRIVATE platform/darwin/src/headless_backend_cgl.cpp
- PRIVATE platform/default/headless_backend.cpp
- PRIVATE platform/default/headless_display.cpp
- PRIVATE platform/default/offscreen_view.cpp
+ PRIVATE platform/default/mbgl/gl/headless_display.hpp
+ PRIVATE platform/darwin/src/headless_display_cgl.cpp
+ PRIVATE platform/default/mbgl/gl/offscreen_view.cpp
+ PRIVATE platform/default/mbgl/gl/offscreen_view.hpp
# Thread pool
- PRIVATE platform/default/thread_pool.cpp
+ PRIVATE platform/default/mbgl/util/default_thread_pool.cpp
+ PRIVATE platform/default/mbgl/util/default_thread_pool.cpp
)
target_add_mason_package(mbgl-core PUBLIC geojson)
+ target_add_mason_package(mbgl-core PUBLIC icu)
target_compile_options(mbgl-core
PRIVATE -fobjc-arc
+ PRIVATE -fvisibility=hidden
)
target_include_directories(mbgl-core
- PRIVATE platform/default
+ PUBLIC platform/darwin
+ PUBLIC platform/default
)
target_link_libraries(mbgl-core
@@ -106,6 +120,10 @@ macro(mbgl_platform_test)
COMPILE_FLAGS -DWORK_DIRECTORY="${CMAKE_SOURCE_DIR}"
)
+ target_compile_options(mbgl-test
+ PRIVATE -fvisibility=hidden
+ )
+
target_link_libraries(mbgl-test
PRIVATE mbgl-loop
PRIVATE "-framework Foundation"
@@ -118,6 +136,10 @@ macro(mbgl_platform_test)
endmacro()
macro(mbgl_platform_benchmark)
+ target_compile_options(mbgl-benchmark
+ PRIVATE -fvisibility=hidden
+ )
+
target_sources(mbgl-benchmark
PRIVATE benchmark/src/main.cpp
)
@@ -140,8 +162,13 @@ macro(mbgl_platform_benchmark)
endmacro()
macro(mbgl_platform_node)
+ target_compile_options(mbgl-node
+ PRIVATE -fvisibility=hidden
+ )
+
target_link_libraries(mbgl-node
PRIVATE "-framework Foundation"
PRIVATE "-framework OpenGL"
+ PRIVATE "-Wl,-bind_at_load"
)
endmacro()
diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj
index e31bd7fa01..fc9e0c74e1 100644
--- a/platform/macos/macos.xcodeproj/project.pbxproj
+++ b/platform/macos/macos.xcodeproj/project.pbxproj
@@ -59,6 +59,8 @@
40E1601D1DF217D6005EA6D9 /* MGLStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 40E1601B1DF216E6005EA6D9 /* MGLStyleLayerTests.m */; };
52BECB0A1CC5A26F009CD791 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52BECB091CC5A26F009CD791 /* SystemConfiguration.framework */; };
5548BE781D09E718005DDE81 /* libmbgl-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE6C3451CC31D1200DB3429 /* libmbgl-core.a */; };
+ 556660C61E1BEA0100E2C41B /* MGLFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 556660C51E1BEA0100E2C41B /* MGLFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 556660D61E1D07E400E2C41B /* MGLVersionNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = 556660D51E1D07E400E2C41B /* MGLVersionNumber.m */; };
558F18221D0B13B100123F46 /* libmbgl-loop.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 558F18211D0B13B000123F46 /* libmbgl-loop.a */; };
55D9B4B11D005D3900C1CCE2 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D9B4B01D005D3900C1CCE2 /* libz.tbd */; };
DA00FC8A1D5EEAC3009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC881D5EEAC3009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -124,6 +126,7 @@
DA8F259C1D51CB000010E6B5 /* MGLStyleValue_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8F259B1D51CB000010E6B5 /* MGLStyleValue_Private.h */; };
DA8F25B21D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8F25A61D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h */; };
DA8F25B31D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25A71D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.mm */; };
+ DAA1BB4A1E2D425C00ABB750 /* libmbgl-loop.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAA1BB491E2D425C00ABB750 /* libmbgl-loop.a */; };
DAA48EFD1D6A4731006A7E36 /* StyleLayerIconTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA48EFC1D6A4731006A7E36 /* StyleLayerIconTransformer.m */; };
DAB2CCE51DF632ED001B2FE1 /* LimeGreenStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = DAB2CCE41DF632ED001B2FE1 /* LimeGreenStyleLayer.m */; };
DAC2ABC51CC6D343006D18C4 /* MGLAnnotationImage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC2ABC41CC6D343006D18C4 /* MGLAnnotationImage_Private.h */; };
@@ -308,6 +311,8 @@
52BECB091CC5A26F009CD791 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
5548BE791D0ACBB2005DDE81 /* libmbgl-loop-darwin.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmbgl-loop-darwin.a"; path = "cmake/Debug/libmbgl-loop-darwin.a"; sourceTree = "<group>"; };
5548BE7B1D0ACBBD005DDE81 /* libmbgl-loop-darwin.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmbgl-loop-darwin.a"; path = "cmake/Debug/libmbgl-loop-darwin.a"; sourceTree = "<group>"; };
+ 556660C51E1BEA0100E2C41B /* MGLFoundation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLFoundation.h; sourceTree = "<group>"; };
+ 556660D51E1D07E400E2C41B /* MGLVersionNumber.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLVersionNumber.m; path = ../../darwin/test/MGLVersionNumber.m; sourceTree = "<group>"; };
558F18211D0B13B000123F46 /* libmbgl-loop.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmbgl-loop.a"; path = "../../build/osx/Debug/libmbgl-loop.a"; sourceTree = "<group>"; };
55D9B4B01D005D3900C1CCE2 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
55FE0E8D1D100A0900FD240B /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = config.xcconfig; path = ../../build/macos/config.xcconfig; sourceTree = "<group>"; };
@@ -354,6 +359,8 @@
DA87A9971DC9D88400810D09 /* MGLTileSetTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSetTests.mm; sourceTree = "<group>"; };
DA87A99B1DC9D8DD00810D09 /* MGLShapeSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeSource_Private.h; sourceTree = "<group>"; };
DA87A99F1DC9DC6200810D09 /* MGLValueEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLValueEvaluator.h; sourceTree = "<group>"; };
+ DA88520F1E0A4D0D009D7AD6 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
+ DA8852101E0A4D3A009D7AD6 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Foundation.strings"; sourceTree = "<group>"; };
DA8933A61CCD287300E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MGLAnnotationCallout.xib; sourceTree = "<group>"; };
DA8933AC1CCD290700E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = "<group>"; };
DA8933B41CCD2C2500E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Foundation.strings; sourceTree = "<group>"; };
@@ -381,6 +388,7 @@
DA8F25B51D51D2240010E6B5 /* MGLStyleLayerTests.mm.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; name = MGLStyleLayerTests.mm.ejs; path = ../test/MGLStyleLayerTests.mm.ejs; sourceTree = "<group>"; };
DA8F25B61D51D2240010E6B5 /* MGLStyleLayer.h.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLStyleLayer.h.ejs; sourceTree = "<group>"; };
DA8F25B71D51D2240010E6B5 /* MGLStyleLayer.mm.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLStyleLayer.mm.ejs; sourceTree = "<group>"; };
+ DAA1BB491E2D425C00ABB750 /* libmbgl-loop.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmbgl-loop.a"; path = "../../build/macos/Debug/libmbgl-loop.a"; sourceTree = "<group>"; };
DAA48EFB1D6A4731006A7E36 /* StyleLayerIconTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleLayerIconTransformer.h; sourceTree = "<group>"; };
DAA48EFC1D6A4731006A7E36 /* StyleLayerIconTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StyleLayerIconTransformer.m; sourceTree = "<group>"; };
DAB2CCE31DF632ED001B2FE1 /* LimeGreenStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LimeGreenStyleLayer.h; sourceTree = "<group>"; };
@@ -512,6 +520,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ DAA1BB4A1E2D425C00ABB750 /* libmbgl-loop.a in Frameworks */,
DAE0DD7A1D5F015A005A6BB1 /* libmbgl-core.a in Frameworks */,
DAE6C3321CC30DB200DB3429 /* Mapbox.framework in Frameworks */,
);
@@ -842,6 +851,7 @@
DAE6C31E1CC308BC00DB3429 /* Frameworks */ = {
isa = PBXGroup;
children = (
+ DAA1BB491E2D425C00ABB750 /* libmbgl-loop.a */,
558F18211D0B13B000123F46 /* libmbgl-loop.a */,
5548BE7B1D0ACBBD005DDE81 /* libmbgl-loop-darwin.a */,
5548BE791D0ACBB2005DDE81 /* libmbgl-loop-darwin.a */,
@@ -889,6 +899,7 @@
DAE6C3CB1CC34BD800DB3429 /* MGLOfflineStorageTests.m */,
35C5D84B1D6DD75B00E95907 /* MGLPredicateTests.mm */,
DAE6C3CC1CC34BD800DB3429 /* MGLStyleTests.mm */,
+ 556660D51E1D07E400E2C41B /* MGLVersionNumber.m */,
DAE6C33A1CC30DB200DB3429 /* Info.plist */,
DA2784FD1DF03060001D5B8D /* Media.xcassets */,
DA35D0891E1A631B007DED41 /* one-liner.json */,
@@ -911,6 +922,7 @@
DA00FC881D5EEAC3009AABC8 /* MGLAttributionInfo.h */,
DAF0D8151DFE6B1800B28378 /* MGLAttributionInfo_Private.h */,
DA00FC891D5EEAC3009AABC8 /* MGLAttributionInfo.mm */,
+ 556660C51E1BEA0100E2C41B /* MGLFoundation.h */,
DAE6C34D1CC31E0400DB3429 /* MGLMapCamera.h */,
DAE6C36E1CC31E2A00DB3429 /* MGLMapCamera.mm */,
DD0902B01DB1AC6400C5BDCE /* MGLNetworkConfiguration.h */,
@@ -965,6 +977,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ 556660C61E1BEA0100E2C41B /* MGLFoundation.h in Headers */,
DA8F258F1D51CA600010E6B5 /* MGLRasterStyleLayer.h in Headers */,
3508EC641D749D39009B0EE4 /* NSExpression+MGLAdditions.h in Headers */,
DAE6C38D1CC31E2A00DB3429 /* MGLOfflineRegion_Private.h in Headers */,
@@ -1163,6 +1176,7 @@
knownRegions = (
en,
Base,
+ "zh-Hans",
);
mainGroup = DA839E891CC2E3400062CAFB;
productRefGroup = DA839E931CC2E3400062CAFB /* Products */;
@@ -1333,6 +1347,7 @@
3599A3E81DF70E2000E77FB2 /* MGLStyleValueTests.m in Sources */,
DAEDC4321D6033F1000224FF /* MGLAttributionInfoTests.m in Sources */,
DA0CD58E1CF56F5800A5F5A5 /* MGLFeatureTests.mm in Sources */,
+ 556660D61E1D07E400E2C41B /* MGLVersionNumber.m in Sources */,
DA2207BC1DC076940002F84D /* MGLStyleValueTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1381,6 +1396,7 @@
isa = PBXVariantGroup;
children = (
DA8933AC1CCD290700E68420 /* Base */,
+ DA88520F1E0A4D0D009D7AD6 /* zh-Hans */,
);
name = Localizable.strings;
sourceTree = "<group>";
@@ -1389,6 +1405,7 @@
isa = PBXVariantGroup;
children = (
DA8933B41CCD2C2500E68420 /* Base */,
+ DA8852101E0A4D3A009D7AD6 /* zh-Hans */,
);
name = Foundation.strings;
sourceTree = "<group>";
@@ -1408,6 +1425,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
@@ -1454,6 +1472,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
@@ -1496,6 +1515,7 @@
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = "$(SRCROOT)/app/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ OTHER_CFLAGS = "-fvisibility=hidden";
PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.MapboxGL;
PRODUCT_NAME = "Mapbox GL";
};
@@ -1508,6 +1528,7 @@
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = "$(SRCROOT)/app/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ OTHER_CFLAGS = "-fvisibility=hidden";
PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.MapboxGL;
PRODUCT_NAME = "Mapbox GL";
};
@@ -1556,6 +1577,7 @@
INFOPLIST_FILE = "$(SRCROOT)/sdk/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
+ OTHER_CFLAGS = "-fvisibility=hidden";
OTHER_LDFLAGS = (
"$(mbgl_core_LINK_LIBRARIES)",
"$(mbgl_loop_LINK_LIBRARIES)",
@@ -1564,7 +1586,7 @@
PRODUCT_NAME = Mapbox;
SKIP_INSTALL = YES;
VERSIONING_SYSTEM = "apple-generic";
- VERSION_INFO_PREFIX = "";
+ VERSION_INFO_PREFIX = "__attribute__((visibility (\"default\"))) ";
};
name = Debug;
};
@@ -1574,7 +1596,9 @@
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
+ DEAD_CODE_STRIPPING = YES;
DEFINES_MODULE = YES;
+ DEPLOYMENT_POSTPROCESSING = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
@@ -1586,6 +1610,7 @@
INFOPLIST_FILE = "$(SRCROOT)/sdk/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
+ OTHER_CFLAGS = "-fvisibility=hidden";
OTHER_LDFLAGS = (
"$(mbgl_core_LINK_LIBRARIES)",
"$(mbgl_loop_LINK_LIBRARIES)",
@@ -1593,8 +1618,9 @@
PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.MapboxGL;
PRODUCT_NAME = Mapbox;
SKIP_INSTALL = YES;
+ STRIP_STYLE = "non-global";
VERSIONING_SYSTEM = "apple-generic";
- VERSION_INFO_PREFIX = "";
+ VERSION_INFO_PREFIX = "__attribute__((visibility (\"default\"))) ";
};
name = Release;
};
@@ -1607,6 +1633,7 @@
HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
INFOPLIST_FILE = test/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+ OTHER_CFLAGS = "-fvisibility=hidden";
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"$(variant_cflags)",
@@ -1630,6 +1657,7 @@
HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
INFOPLIST_FILE = test/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+ OTHER_CFLAGS = "-fvisibility=hidden";
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"$(variant_cflags)",
diff --git a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/CI.xcscheme b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
index eca3be86dc..a049928fdd 100644
--- a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
+++ b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0800"
+ LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
diff --git a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme
index 189596d94f..95351f7f04 100644
--- a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme
+++ b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0800"
+ LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
diff --git a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme
index 0867fc0c23..a58ef5c9cf 100644
--- a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme
+++ b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0800"
+ LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
diff --git a/platform/macos/scripts/executable.xcscheme b/platform/macos/scripts/executable.xcscheme
index 4353aad846..c6a8d04d30 100644
--- a/platform/macos/scripts/executable.xcscheme
+++ b/platform/macos/scripts/executable.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0730"
+ LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -46,7 +46,8 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
- useCustomWorkingDirectory = "NO"
+ useCustomWorkingDirectory = "YES"
+ customWorkingDirectory = "{{WORKING_DIRECTORY}}"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
@@ -81,7 +82,8 @@
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
- useCustomWorkingDirectory = "NO"
+ useCustomWorkingDirectory = "YES"
+ customWorkingDirectory = "{{WORKING_DIRECTORY}}"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
diff --git a/platform/macos/scripts/library.xcscheme b/platform/macos/scripts/library.xcscheme
index 012bc900c2..5472d3c821 100644
--- a/platform/macos/scripts/library.xcscheme
+++ b/platform/macos/scripts/library.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0730"
+ LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
diff --git a/platform/macos/scripts/metrics.sh b/platform/macos/scripts/metrics.sh
new file mode 100755
index 0000000000..56790fc1e6
--- /dev/null
+++ b/platform/macos/scripts/metrics.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+set -e
+set -o pipefail
+
+# Track individual architectures
+scripts/log_binary_size.sh "build/macos/pkg/Mapbox.framework/Versions/Current/Mapbox" "Platform=macOS,Arch=x86_64"
diff --git a/platform/macos/scripts/node.xcscheme b/platform/macos/scripts/node.xcscheme
index 361ed58a37..6f541deca3 100644
--- a/platform/macos/scripts/node.xcscheme
+++ b/platform/macos/scripts/node.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0730"
+ LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -76,7 +76,8 @@
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
- useCustomWorkingDirectory = "NO"
+ useCustomWorkingDirectory = "YES"
+ customWorkingDirectory = "{{WORKING_DIRECTORY}}"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
diff --git a/platform/macos/scripts/package.sh b/platform/macos/scripts/package.sh
index f8c24a17fa..6ae0cc65cc 100755
--- a/platform/macos/scripts/package.sh
+++ b/platform/macos/scripts/package.sh
@@ -88,3 +88,6 @@ sed -n -e '/^## /,$p' platform/macos/CHANGELOG.md > "${OUTPUT}/CHANGELOG.md"
step "Generating API documentation…"
make xdocument OUTPUT="${OUTPUT}/documentation"
+
+step "Checking that all public symbols are exported…"
+node platform/darwin/scripts/check-public-symbols.js macOS
diff --git a/platform/macos/sdk/zh-Hans.lproj/Localizable.strings b/platform/macos/sdk/zh-Hans.lproj/Localizable.strings
new file mode 100644
index 0000000000..40b61a2dba
--- /dev/null
+++ b/platform/macos/sdk/zh-Hans.lproj/Localizable.strings
@@ -0,0 +1,15 @@
+/* Accessibility title */
+"MAP_A11Y_TITLE" = "Mapbox";
+
+/* Label of Zoom In button */
+"ZOOM_IN_LABEL" = "+";
+
+/* Tooltip of Zoom In button */
+"ZOOM_IN_TOOLTIP" = "放大";
+
+/* Label of Zoom Out button; U+2212 MINUS SIGN */
+"ZOOM_OUT_LABEL" = "−";
+
+/* Tooltip of Zoom Out button */
+"ZOOM_OUT_TOOLTIP" = "缩小";
+
diff --git a/platform/macos/src/MGLAnnotationImage.h b/platform/macos/src/MGLAnnotationImage.h
index 2738ea654c..0f248c721c 100644
--- a/platform/macos/src/MGLAnnotationImage.h
+++ b/platform/macos/src/MGLAnnotationImage.h
@@ -1,5 +1,7 @@
#import <AppKit/AppKit.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
@@ -8,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN
`NSImage` objects with annotation-related metadata. They may be recycled later
and put into a reuse queue that is maintained by the map view.
*/
+MGL_EXPORT
@interface MGLAnnotationImage : NSObject <NSSecureCoding>
#pragma mark Initializing and Preparing the Image Object
diff --git a/platform/macos/src/MGLAttributionButton.h b/platform/macos/src/MGLAttributionButton.h
index 88fcdadf78..3e0b53a6d0 100644
--- a/platform/macos/src/MGLAttributionButton.h
+++ b/platform/macos/src/MGLAttributionButton.h
@@ -1,5 +1,6 @@
#import <Cocoa/Cocoa.h>
+#import "MGLFoundation.h"
#import "MGLTypes.h"
NS_ASSUME_NONNULL_BEGIN
@@ -7,6 +8,7 @@ NS_ASSUME_NONNULL_BEGIN
@class MGLAttributionInfo;
/// Button that looks like a hyperlink and opens a URL.
+MGL_EXPORT
@interface MGLAttributionButton : NSButton
/// Returns an `MGLAttributionButton` instance with the given info.
diff --git a/platform/macos/src/MGLMapView.h b/platform/macos/src/MGLMapView.h
index 954e5a2c75..efe83d1573 100644
--- a/platform/macos/src/MGLMapView.h
+++ b/platform/macos/src/MGLMapView.h
@@ -1,6 +1,7 @@
#import <Cocoa/Cocoa.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLTypes.h"
#import "MGLGeometry.h"
@@ -47,7 +48,7 @@ NS_ASSUME_NONNULL_BEGIN
@note You are responsible for getting permission to use the map data and for
ensuring that your use adheres to the relevant terms of use.
*/
-IB_DESIGNABLE
+MGL_EXPORT IB_DESIGNABLE
@interface MGLMapView : NSView
#pragma mark Creating Instances
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index 7bd8f3369e..0db059dcf2 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -19,13 +19,13 @@
#import "MGLAnnotationImage.h"
#import "MGLMapViewDelegate.h"
-#import <mbgl/mbgl.hpp>
+#import <mbgl/map/map.hpp>
+#import <mbgl/map/view.hpp>
#import <mbgl/annotation/annotation.hpp>
#import <mbgl/map/camera.hpp>
-#import <mbgl/platform/darwin/reachability.h>
-#import <mbgl/platform/default/thread_pool.hpp>
+#import <mbgl/storage/reachability.h>
+#import <mbgl/util/default_thread_pool.hpp>
#import <mbgl/gl/extension.hpp>
-#import <mbgl/gl/gl.hpp>
#import <mbgl/gl/context.hpp>
#import <mbgl/map/backend.hpp>
#import <mbgl/sprite/sprite_image.hpp>
@@ -260,10 +260,8 @@ public:
mbgl::DefaultFileSource* mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
- const std::array<uint16_t, 2> size = {{ static_cast<uint16_t>(self.bounds.size.width),
- static_cast<uint16_t>(self.bounds.size.height) }};
_mbglThreadPool = new mbgl::ThreadPool(4);
- _mbglMap = new mbgl::Map(*_mbglView, size, [NSScreen mainScreen].backingScaleFactor, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
+ _mbglMap = new mbgl::Map(*_mbglView, self.size, [NSScreen mainScreen].backingScaleFactor, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
[self validateTileCacheSize];
// Install the OpenGL layer. Interface Builder’s synchronous drawing means
@@ -303,6 +301,16 @@ public:
_pendingLongitude = NAN;
}
+- (mbgl::Size)size {
+ return { static_cast<uint32_t>(self.bounds.size.width),
+ static_cast<uint32_t>(self.bounds.size.height) };
+}
+
+- (mbgl::Size)framebufferSize {
+ NSRect bounds = [self convertRectToBacking:self.bounds];
+ return { static_cast<uint32_t>(bounds.size.width), static_cast<uint32_t>(bounds.size.height) };
+}
+
/// Adds zoom controls to the lower-right corner.
- (void)installZoomControls {
_zoomControls = [[NSSegmentedControl alloc] initWithFrame:NSZeroRect];
@@ -677,8 +685,7 @@ public:
[self validateTileCacheSize];
}
if (!_isTargetingInterfaceBuilder) {
- _mbglMap->setSize({{ static_cast<uint16_t>(self.bounds.size.width),
- static_cast<uint16_t>(self.bounds.size.height) }});
+ _mbglMap->setSize(self.size);
}
}
@@ -2664,14 +2671,14 @@ public:
}
mbgl::gl::value::Viewport::Type getViewport() const {
- return { 0, 0, static_cast<uint16_t>(nativeView.bounds.size.width),
- static_cast<uint16_t>(nativeView.bounds.size.height) };
+ return { 0, 0, nativeView.framebufferSize };
}
void updateViewBinding() {
fbo = mbgl::gl::value::BindFramebuffer::Get();
getContext().bindFramebuffer.setCurrentValue(fbo);
getContext().viewport.setCurrentValue(getViewport());
+ assert(mbgl::gl::value::Viewport::Get() == getContext().viewport.getCurrentValue());
}
void bind() override {
@@ -2680,23 +2687,7 @@ public:
}
mbgl::PremultipliedImage readStillImage() {
- NSRect bounds = [nativeView convertRectToBacking:nativeView.bounds];
- const uint16_t width = bounds.size.width;
- const uint16_t height = bounds.size.height;
- mbgl::PremultipliedImage image{ width, height };
- MBGL_CHECK_ERROR(
- glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
-
- const size_t stride = image.stride();
- auto tmp = std::make_unique<uint8_t[]>(stride);
- uint8_t *rgba = image.data.get();
- for (int i = 0, j = height - 1; i < j; i++, j--) {
- std::memcpy(tmp.get(), rgba + i * stride, stride);
- std::memcpy(rgba + i * stride, rgba + j * stride, stride);
- std::memcpy(rgba + j * stride, tmp.get(), stride);
- }
-
- return image;
+ return getContext().readFramebuffer<mbgl::PremultipliedImage>(nativeView.framebufferSize);
}
private:
diff --git a/platform/macos/src/MGLOpenGLLayer.mm b/platform/macos/src/MGLOpenGLLayer.mm
index e8fa521351..296e30179b 100644
--- a/platform/macos/src/MGLOpenGLLayer.mm
+++ b/platform/macos/src/MGLOpenGLLayer.mm
@@ -2,8 +2,6 @@
#import "MGLMapView_Private.h"
-#import <mbgl/gl/gl.hpp>
-
@implementation MGLOpenGLLayer
- (MGLMapView *)mapView {
diff --git a/platform/macos/src/Mapbox.h b/platform/macos/src/Mapbox.h
index 5b3be3ea67..1f30497184 100644
--- a/platform/macos/src/Mapbox.h
+++ b/platform/macos/src/Mapbox.h
@@ -1,10 +1,12 @@
#import <Cocoa/Cocoa.h>
+#import "MGLFoundation.h"
+
/// Project version number for Mapbox.
-FOUNDATION_EXPORT double MapboxVersionNumber;
+FOUNDATION_EXPORT MGL_EXPORT double MapboxVersionNumber;
/// Project version string for Mapbox.
-FOUNDATION_EXPORT const unsigned char MapboxVersionString[];
+FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLAccountManager.h"
#import "MGLAnnotation.h"
diff --git a/platform/macos/src/NSImage+MGLAdditions.mm b/platform/macos/src/NSImage+MGLAdditions.mm
index e8e84f0a03..9c30d3c37b 100644
--- a/platform/macos/src/NSImage+MGLAdditions.mm
+++ b/platform/macos/src/NSImage+MGLAdditions.mm
@@ -21,8 +21,8 @@
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:{ NSZeroPoint, self.size }];
[self unlockFocus];
- mbgl::PremultipliedImage cPremultipliedImage(rep.pixelsWide, rep.pixelsHigh);
- std::copy(rep.bitmapData, rep.bitmapData + cPremultipliedImage.size(), cPremultipliedImage.data.get());
+ mbgl::PremultipliedImage cPremultipliedImage({ static_cast<uint32_t>(rep.pixelsWide), static_cast<uint32_t>(rep.pixelsHigh) });
+ std::copy(rep.bitmapData, rep.bitmapData + cPremultipliedImage.bytes(), cPremultipliedImage.data.get());
return std::make_unique<mbgl::SpriteImage>(std::move(cPremultipliedImage),
(float)(rep.pixelsWide / self.size.width),
[self isTemplate]);
diff --git a/platform/node/CHANGELOG.md b/platform/node/CHANGELOG.md
index d64aa5238c..6f5afbbd6c 100644
--- a/platform/node/CHANGELOG.md
+++ b/platform/node/CHANGELOG.md
@@ -1,3 +1,25 @@
+# 3.4.4 - January 10, 2017
+
+- Updates the node binary publish location on s3 to reflect new package name ([#7653](https://github.com/mapbox/mapbox-gl-native/pull/7653))
+
+# 3.4.3 - January 9, 2017
+
+- Adds `map.addImage()` and `map.removeImage()` APIs ([#7610](https://github.com/mapbox/mapbox-gl-native/pull/7610))
+
+# 3.4.2 - November 15, 2016
+
+- Switches back to publishing Linux binaries with GLX, to eliminate a runtime dependency on `libOSMesa.so.8` and enable dynamically linking against `libGL.so` provided by an alternate implementation, such as the NVIDIA proproetary drivers ([#7503](https://github.com/mapbox/mapbox-gl-native/pull/7053))
+
+# 3.4.1 - November 10, 2016
+
+- Skips assigning clip IDs to tiles that won't be rendered, mitigating a `stencil mask overflow` error ([#6871](https://github.com/mapbox/mapbox-gl-native/pull/6871))
+- Fixes camera logic to avoid unnecessary or redundant setting of camera options ([#6990](https://github.com/mapbox/mapbox-gl-native/pull/6990))
+
+# 3.4.0 - November 2, 2016
+
+- Fixes Bitrise configuration to automatically publish macOS binaries ([#6789](https://github.com/mapbox/mapbox-gl-native/pull/6789))
+- Switches from using individual thread pools for each `mbgl::Map` object to sharing the built-in Node.js thread pool for NodeMap implementations ([#6687](https://github.com/mapbox/mapbox-gl-native/pull/6687))
+
# 3.3.3 - September 6, 2016
- Switches to using a NodeRequest member function (with a JavaScript shim in front to preserve the API) instead of a new `v8::Context` to avoid a memory leak ([#5704](https://github.com/mapbox/mapbox-gl-native/pull/5704))
diff --git a/platform/node/bitrise.yml b/platform/node/bitrise.yml
index 998e97301b..0323f944a3 100644
--- a/platform/node/bitrise.yml
+++ b/platform/node/bitrise.yml
@@ -57,6 +57,7 @@ workflows:
#!/bin/bash
set -eu -o pipefail
make test-node || envman add --key RESULT --value $?
+ ./platform/node/scripts/after_script.sh ${BITRISE_BUILD_NUMBER}
- script:
title: Run publish script
run_if: '{{enveq "SKIPCI" "false"}}'
@@ -64,7 +65,7 @@ workflows:
- content: |-
#!/bin/bash
set -eu -o pipefail
- ./platform/node/scripts/after_script.sh ${BITRISE_BUILD_NUMBER}
+ ./platform/node/scripts/after_success.sh
exit ${RESULT:-0}
- slack:
title: Post to Slack
diff --git a/platform/node/scripts/after_script.sh b/platform/node/scripts/after_script.sh
index c805e453a2..beb8d6966f 100755
--- a/platform/node/scripts/after_script.sh
+++ b/platform/node/scripts/after_script.sh
@@ -5,19 +5,10 @@ set -o pipefail
JOB=$1
-if [[ -n ${PUBLISH:-} ]]; then
- if [[ "${BUILDTYPE}" == "Debug" ]]; then
- echo "Please run this script in release mode (BUILDTYPE=Release)."
- exit 1
- else
- ./node_modules/.bin/node-pre-gyp package publish info
- fi
-else
- if [ ! -z "${AWS_ACCESS_KEY_ID}" ] && [ ! -z "${AWS_SECRET_ACCESS_KEY}" ] ; then
- gzip --stdout node_modules/mapbox-gl-test-suite/render-tests/index.html | \
- aws s3 cp --acl public-read --content-encoding gzip --content-type text/html \
- - s3://mapbox/mapbox-gl-native/render-tests/$JOB/index.html
+if [ ! -z "${AWS_ACCESS_KEY_ID}" ] && [ ! -z "${AWS_SECRET_ACCESS_KEY}" ] ; then
+ gzip --stdout mapbox-gl-js/test/integration/render-tests/index.html | \
+ aws s3 cp --acl public-read --content-encoding gzip --content-type text/html \
+ - s3://mapbox/mapbox-gl-native/render-tests/$JOB/index.html
- echo http://mapbox.s3.amazonaws.com/mapbox-gl-native/render-tests/$JOB/index.html
- fi
+ echo http://mapbox.s3.amazonaws.com/mapbox-gl-native/render-tests/$JOB/index.html
fi
diff --git a/platform/node/scripts/after_success.sh b/platform/node/scripts/after_success.sh
new file mode 100755
index 0000000000..7ef8f53545
--- /dev/null
+++ b/platform/node/scripts/after_success.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+set -e
+set -o pipefail
+
+if [[ -n ${PUBLISH:-} ]]; then
+ if [[ "${BUILDTYPE}" == "Debug" ]]; then
+ echo "Please run this script in release mode (BUILDTYPE=Release)."
+ exit 1
+ else
+ ./node_modules/.bin/node-pre-gyp package publish info
+ fi
+fi
diff --git a/platform/node/src/node_conversion.hpp b/platform/node/src/node_conversion.hpp
index 6ebc846d11..22daedef6a 100644
--- a/platform/node/src/node_conversion.hpp
+++ b/platform/node/src/node_conversion.hpp
@@ -36,7 +36,7 @@ inline v8::Local<v8::Value> arrayMember(v8::Local<v8::Value> value, std::size_t
inline bool isObject(v8::Local<v8::Value> value) {
Nan::HandleScope scope;
- return value->IsObject();
+ return value->IsObject() && !value->IsArray();
}
inline optional<v8::Local<v8::Value>> objectMember(v8::Local<v8::Value> value, const char * name) {
diff --git a/platform/node/src/node_log.cpp b/platform/node/src/node_logging.cpp
index 0a97ebce36..5e7326e90a 100644
--- a/platform/node/src/node_log.cpp
+++ b/platform/node/src/node_logging.cpp
@@ -1,4 +1,4 @@
-#include "node_log.hpp"
+#include "node_logging.hpp"
#include <mbgl/util/enum.hpp>
diff --git a/platform/node/src/node_log.hpp b/platform/node/src/node_logging.hpp
index a19c61284b..a12603ba6e 100644
--- a/platform/node/src/node_log.hpp
+++ b/platform/node/src/node_logging.hpp
@@ -2,7 +2,7 @@
#include "util/async_queue.hpp"
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp
index 671bf3e0fd..ea3517f2a6 100644
--- a/platform/node/src/node_map.cpp
+++ b/platform/node/src/node_map.cpp
@@ -4,11 +4,12 @@
#include "node_conversion.hpp"
#include "node_geojson.hpp"
-#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/gl/headless_display.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/style/conversion/source.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/filter.hpp>
+#include <mbgl/sprite/sprite_image.cpp>
#include <unistd.h>
@@ -58,11 +59,15 @@ void NodeMap::Init(v8::Local<v8::Object> target) {
Nan::SetPrototypeMethod(tpl, "addSource", AddSource);
Nan::SetPrototypeMethod(tpl, "addLayer", AddLayer);
Nan::SetPrototypeMethod(tpl, "removeLayer", RemoveLayer);
+ Nan::SetPrototypeMethod(tpl, "addImage", AddImage);
+ Nan::SetPrototypeMethod(tpl, "removeImage", RemoveLayer);
Nan::SetPrototypeMethod(tpl, "setLayoutProperty", SetLayoutProperty);
Nan::SetPrototypeMethod(tpl, "setPaintProperty", SetPaintProperty);
Nan::SetPrototypeMethod(tpl, "setFilter", SetFilter);
Nan::SetPrototypeMethod(tpl, "setCenter", SetCenter);
+ Nan::SetPrototypeMethod(tpl, "setZoom", SetZoom);
Nan::SetPrototypeMethod(tpl, "setBearing", SetBearing);
+ Nan::SetPrototypeMethod(tpl, "setPitch", SetPitch);
Nan::SetPrototypeMethod(tpl, "dumpDebugLogs", DumpDebugLogs);
Nan::SetPrototypeMethod(tpl, "queryRenderedFeatures", QueryRenderedFeatures);
@@ -356,20 +361,39 @@ void NodeMap::Render(const Nan::FunctionCallbackInfo<v8::Value>& info) {
}
void NodeMap::startRender(NodeMap::RenderOptions options) {
- map->setSize(std::array<uint16_t, 2>{{ static_cast<uint16_t>(options.width),
- static_cast<uint16_t>(options.height) }});
+ map->setSize({ options.width, options.height });
- const std::array<uint16_t, 2> fbSize{{ static_cast<uint16_t>(options.width * pixelRatio),
- static_cast<uint16_t>(options.height * pixelRatio) }};
- if (!view || view->getSize() != fbSize) {
+ const mbgl::Size fbSize{ static_cast<uint32_t>(options.width * pixelRatio),
+ static_cast<uint32_t>(options.height * pixelRatio) };
+ if (!view || view->size != fbSize) {
view.reset();
view = std::make_unique<mbgl::OffscreenView>(backend.getContext(), fbSize);
}
- map->setClasses(options.classes);
- map->setLatLngZoom(mbgl::LatLng(options.latitude, options.longitude), options.zoom);
- map->setBearing(options.bearing);
- map->setPitch(options.pitch);
- map->setDebug(options.debugOptions);
+
+ if (map->getClasses() != options.classes) {
+ map->setClasses(options.classes);
+ }
+
+ if (map->getZoom() != options.zoom) {
+ map->setZoom(options.zoom);
+ }
+
+ mbgl::LatLng latLng(options.latitude, options.longitude);
+ if (map->getLatLng() != latLng) {
+ map->setLatLng(latLng);
+ }
+
+ if (map->getBearing() != options.bearing) {
+ map->setBearing(options.bearing);
+ }
+
+ if (map->getPitch() != options.pitch) {
+ map->setPitch(options.pitch);
+ }
+
+ if (map->getDebug() != options.debugOptions) {
+ map->setDebug(options.debugOptions);
+ }
map->renderStill(*view, [this](const std::exception_ptr eptr) {
if (eptr) {
@@ -430,7 +454,7 @@ void NodeMap::renderFinished() {
cb->Call(1, argv);
} else if (img.data) {
v8::Local<v8::Object> pixels = Nan::NewBuffer(
- reinterpret_cast<char *>(img.data.get()), img.size(),
+ reinterpret_cast<char *>(img.data.get()), img.bytes(),
// Retain the data until the buffer is deleted.
[](char *, void * hint) {
delete [] reinterpret_cast<uint8_t*>(hint);
@@ -558,6 +582,82 @@ void NodeMap::RemoveLayer(const Nan::FunctionCallbackInfo<v8::Value>& info) {
nodeMap->map->removeLayer(*Nan::Utf8String(info[0]));
}
+
+void NodeMap::AddImage(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ using namespace mbgl::style;
+ using namespace mbgl::style::conversion;
+
+ auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
+ if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
+
+ if (info.Length() != 3) {
+ return Nan::ThrowTypeError("Three arguments required");
+ }
+
+ if (!info[0]->IsString()) {
+ return Nan::ThrowTypeError("First argument must be a string");
+ }
+
+ if (!info[1]->IsObject()) {
+ return Nan::ThrowTypeError("Second argument must be an object");
+ }
+
+ if (!info[2]->IsObject()) {
+ return Nan::ThrowTypeError("Third argument must be an object");
+ }
+
+ auto optionObject = Nan::To<v8::Object>(info[2]).ToLocalChecked();
+
+ if (!Nan::Get(optionObject, Nan::New("height").ToLocalChecked()).ToLocalChecked()->IsUint32()) {
+ return Nan::ThrowTypeError("height parameter required");
+ }
+
+ if (!Nan::Get(optionObject, Nan::New("width").ToLocalChecked()).ToLocalChecked()->IsUint32()) {
+ return Nan::ThrowTypeError("width parameter required");
+ }
+
+ if (!Nan::Get(optionObject, Nan::New("pixelRatio").ToLocalChecked()).ToLocalChecked()->IsUint32()) {
+ return Nan::ThrowTypeError("pixelRatio parameter required");
+ }
+
+ uint32_t imageHeight = Nan::Get(optionObject, Nan::New("height").ToLocalChecked()).ToLocalChecked()->Uint32Value();
+ uint32_t imageWidth = Nan::Get(optionObject, Nan::New("width").ToLocalChecked()).ToLocalChecked()->Uint32Value();
+
+ if (imageWidth > 1024 || imageHeight > 1024) {
+ return Nan::ThrowTypeError("Max height and width is 1024");
+ }
+
+ uint32_t pixelRatio = Nan::Get(optionObject, Nan::New("pixelRatio").ToLocalChecked()).ToLocalChecked()->Uint32Value();
+ auto imageBuffer = Nan::To<v8::Object>(info[1]).ToLocalChecked()->ToObject();
+
+ if (node::Buffer::Length(imageBuffer) != imageHeight * imageWidth * 4) {
+ return Nan::ThrowTypeError("Image size does not match buffer size");
+ }
+
+ std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(node::Buffer::Length(imageBuffer));
+ std::copy(node::Buffer::Data(imageBuffer), node::Buffer::Data(imageBuffer) + node::Buffer::Length(imageBuffer), data.get());
+ mbgl::PremultipliedImage cPremultipliedImage({ imageWidth, imageHeight}, std::move(data));
+
+ nodeMap->map->addImage(*Nan::Utf8String(info[0]), std::make_unique<mbgl::SpriteImage>(std::move(cPremultipliedImage), pixelRatio));
+}
+
+void NodeMap::RemoveImage(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ using namespace mbgl::style;
+ using namespace mbgl::style::conversion;
+
+ auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
+ if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
+
+ if (info.Length() != 1) {
+ return Nan::ThrowTypeError("One argument required");
+ }
+
+ if (!info[0]->IsString()) {
+ return Nan::ThrowTypeError("First argument must be a string");
+ }
+
+ nodeMap->map->removeImage(*Nan::Utf8String(info[0]));
+}
void NodeMap::SetLayoutProperty(const Nan::FunctionCallbackInfo<v8::Value>& info) {
using namespace mbgl::style;
@@ -706,6 +806,23 @@ void NodeMap::SetCenter(const Nan::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().SetUndefined();
}
+void NodeMap::SetZoom(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
+ if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
+
+ if (info.Length() <= 0 || !info[0]->IsNumber()) {
+ return Nan::ThrowTypeError("First argument must be a number");
+ }
+
+ try {
+ nodeMap->map->setZoom(info[0]->NumberValue());
+ } catch (const std::exception &ex) {
+ return Nan::ThrowError(ex.what());
+ }
+
+ info.GetReturnValue().SetUndefined();
+}
+
void NodeMap::SetBearing(const Nan::FunctionCallbackInfo<v8::Value>& info) {
auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
@@ -723,6 +840,23 @@ void NodeMap::SetBearing(const Nan::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().SetUndefined();
}
+void NodeMap::SetPitch(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
+ if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
+
+ if (info.Length() <= 0 || !info[0]->IsNumber()) {
+ return Nan::ThrowTypeError("First argument must be a number");
+ }
+
+ try {
+ nodeMap->map->setPitch(info[0]->NumberValue());
+ } catch (const std::exception &ex) {
+ return Nan::ThrowError(ex.what());
+ }
+
+ info.GetReturnValue().SetUndefined();
+}
+
void NodeMap::DumpDebugLogs(const Nan::FunctionCallbackInfo<v8::Value>& info) {
auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
@@ -790,7 +924,7 @@ NodeMap::NodeMap(v8::Local<v8::Object> options)
}()),
backend(sharedDisplay()),
map(std::make_unique<mbgl::Map>(backend,
- std::array<uint16_t, 2>{{ 256, 256 }},
+ mbgl::Size{ 256, 256 },
pixelRatio,
*this,
threadpool,
diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp
index 45de2733cc..47a5385ad6 100644
--- a/platform/node/src/node_map.hpp
+++ b/platform/node/src/node_map.hpp
@@ -4,8 +4,8 @@
#include <mbgl/map/map.hpp>
#include <mbgl/storage/file_source.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
@@ -37,11 +37,15 @@ public:
static void AddSource(const Nan::FunctionCallbackInfo<v8::Value>&);
static void AddLayer(const Nan::FunctionCallbackInfo<v8::Value>&);
static void RemoveLayer(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void AddImage(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void RemoveImage(const Nan::FunctionCallbackInfo<v8::Value>&);
static void SetLayoutProperty(const Nan::FunctionCallbackInfo<v8::Value>&);
static void SetPaintProperty(const Nan::FunctionCallbackInfo<v8::Value>&);
static void SetFilter(const Nan::FunctionCallbackInfo<v8::Value>&);
static void SetCenter(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void SetZoom(const Nan::FunctionCallbackInfo<v8::Value>&);
static void SetBearing(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void SetPitch(const Nan::FunctionCallbackInfo<v8::Value>&);
static void DumpDebugLogs(const Nan::FunctionCallbackInfo<v8::Value>&);
static void QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&);
diff --git a/platform/node/src/node_mapbox_gl_native.cpp b/platform/node/src/node_mapbox_gl_native.cpp
index 042def9fdd..cdcc982220 100644
--- a/platform/node/src/node_mapbox_gl_native.cpp
+++ b/platform/node/src/node_mapbox_gl_native.cpp
@@ -8,7 +8,7 @@
#include <mbgl/util/run_loop.hpp>
#include "node_map.hpp"
-#include "node_log.hpp"
+#include "node_logging.hpp"
#include "node_request.hpp"
void RegisterModule(v8::Local<v8::Object> target, v8::Local<v8::Object> module) {
diff --git a/platform/node/test/fixtures/zoom-center/expected.png b/platform/node/test/fixtures/zoom-center/expected.png
new file mode 100644
index 0000000000..93365c04d2
--- /dev/null
+++ b/platform/node/test/fixtures/zoom-center/expected.png
Binary files differ
diff --git a/platform/node/test/js/map.test.js b/platform/node/test/js/map.test.js
index 7321572637..145f62ef5f 100644
--- a/platform/node/test/js/map.test.js
+++ b/platform/node/test/js/map.test.js
@@ -111,11 +111,15 @@ test('Map', function(t) {
'addSource',
'addLayer',
'removeLayer',
+ 'addImage',
+ 'removeImage',
'setLayoutProperty',
'setPaintProperty',
'setFilter',
'setCenter',
+ 'setZoom',
'setBearing',
+ 'setPitch',
'dumpDebugLogs',
'queryRenderedFeatures'
]);
@@ -127,6 +131,164 @@ test('Map', function(t) {
t.end();
});
+ t.test('.addImage', function(t) {
+ var options = {
+ request: function() {},
+ ratio: 1
+ };
+
+ t.test('requires 3 arguments', function(t) {
+ var map = new mbgl.Map(options);
+
+ t.throws(function() {
+ map.addImage();
+ }, /Three arguments required/);
+
+ map.release();
+ t.end();
+ });
+
+ t.test('requires image argument to be an object', function(t) {
+ var map = new mbgl.Map(options);
+
+ t.throws(function() {
+ map.addImage('foo', '', {});
+ }, /Second argument must be an object/);
+
+ map.release();
+ t.end();
+ });
+
+ t.test('requires options argument to have a height param', function(t) {
+ var map = new mbgl.Map(options);
+
+ t.throws(function() {
+ map.addImage('foo', {}, {
+ width: 40,
+ pixelRatio: 2
+ });
+ }, /height parameter required/);
+
+ map.release();
+ t.end();
+ });
+
+ t.test('requires options argument to have a pixelRatio param', function(t) {
+ var map = new mbgl.Map(options);
+
+ t.throws(function() {
+ map.addImage('foo', {}, {
+ width: 40,
+ height: 40
+ });
+ }, /pixelRatio parameter required/);
+
+ map.release();
+ t.end();
+ });
+
+ t.test('requires specified height to be actual height of image', function(t) {
+ var map = new mbgl.Map(options);
+
+ t.throws(function() {
+ map.addImage('foo', new Buffer(''), {
+ width: 401,
+ height: 400,
+ pixelRatio: 1
+ }, 'Image size does not match buffer size');
+ });
+
+ map.release();
+ t.end();
+ });
+
+ t.test('requires height and width to be less than 1024', function(t) {
+ var map = new mbgl.Map(options);
+
+ t.throws(function() {
+ map.addImage('foo', new Buffer(''), {
+ width: 1025,
+ height: 1025,
+ pixelRatio: 1
+ }, 'Max height and width is 1024');
+ });
+
+ map.release();
+ t.end();
+ });
+
+
+ t.test('requires specified height to be actual height of image', function(t) {
+ var map = new mbgl.Map(options);
+
+ t.throws(function() {
+ map.addImage('foo', new Buffer(' '), {
+ width: 401,
+ height: 400,
+ pixelRatio: 1
+ }, 'Image size does not match buffer size');
+ });
+
+ map.release();
+ t.end();
+ });
+
+ t.test('No error', function(t) {
+ var map = new mbgl.Map(options);
+
+ t.doesNotThrow(function() {
+ map.addImage('foo', new Buffer(' '), {
+ width: 1,
+ height: 1,
+ pixelRatio: 1
+ });
+ });
+
+ map.release();
+ t.end();
+ });
+ });
+
+ t.test('.removeImage', function(t) {
+ var options = {
+ request: function() {},
+ ratio: 1
+ };
+
+ t.test('requires one argument', function(t) {
+ var map = new mbgl.Map(options);
+
+ t.throws(function() {
+ map.removeImage();
+ }, /One argument required/);
+
+ map.release();
+ t.end();
+ });
+
+ t.test('requires string as first argument', function(t) {
+ var map = new mbgl.Map(options);
+
+ t.throws(function() {
+ map.removeImage({});
+ }, /First argument must be a string/);
+
+ map.release();
+ t.end();
+ });
+
+ t.test('removes image', function(t) {
+ var map = new mbgl.Map(options);
+
+ t.doesNotThrow(function() {
+ map.removeImage('fooBar');
+ });
+
+ map.release();
+ t.end();
+ });
+ });
+
t.test('.load', function(t) {
var options = {
request: function() {},
@@ -369,6 +531,48 @@ test('Map', function(t) {
map.release();
t.end();
});
+
+ // This can't be tested with a test-suite render test because zoom and center
+ // are set via a different code path when included as style properties.
+ t.test('sets zoom before center', function(t) {
+ var map = new mbgl.Map(options);
+ map.load({
+ "version": 8,
+ "sources": {
+ "geojson": {
+ "type": "geojson",
+ "data": {
+ "type": "Point",
+ "coordinates": [
+ 18.05489,
+ 59.32744
+ ]
+ }
+ }
+ },
+ "layers": [
+ {
+ "id": "circle",
+ "type": "circle",
+ "source": "geojson",
+ "paint": {
+ "circle-color": "red"
+ }
+ }
+ ]
+ });
+ map.render({width: 400, height: 400, zoom: 5, center: [18.05489, 59.32744]}, function(err, actual) {
+ t.error(err);
+
+ var PNG = require('pngjs').PNG;
+ var pixelmatch = require('pixelmatch');
+ var expected = PNG.sync.read(
+ fs.readFileSync(path.join(__dirname, '../fixtures/zoom-center/expected.png'))).data;
+ var numPixels = pixelmatch(actual, expected, undefined, 400, 400, { threshold: 0.13 });
+ t.equal(numPixels, 0);
+ t.end();
+ });
+ })
});
t.test('request callback', function (t) {
diff --git a/platform/node/test/query.test.js b/platform/node/test/query.test.js
index 1309c03467..8125f1c7cd 100644
--- a/platform/node/test/query.test.js
+++ b/platform/node/test/query.test.js
@@ -1,6 +1,6 @@
'use strict';
-var suite = require('mapbox-gl-test-suite').query;
+var suite = require('../../../mapbox-gl-js/test/integration').query;
var suiteImplementation = require('./suite_implementation');
var tests;
diff --git a/platform/node/test/render.test.js b/platform/node/test/render.test.js
index 0527a19070..e2e13534c9 100644
--- a/platform/node/test/render.test.js
+++ b/platform/node/test/render.test.js
@@ -1,6 +1,6 @@
'use strict';
-var suite = require('mapbox-gl-test-suite').render;
+var suite = require('../../../mapbox-gl-js/test/integration').render;
var suiteImplementation = require('./suite_implementation');
var tests;
diff --git a/platform/node/test/suite_implementation.js b/platform/node/test/suite_implementation.js
index bde8acde18..6648757a98 100644
--- a/platform/node/test/suite_implementation.js
+++ b/platform/node/test/suite_implementation.js
@@ -2,6 +2,9 @@
var mbgl = require('../index');
var request = require('request');
+var PNG = require('pngjs').PNG;
+var fs = require('fs');
+var path = require('path');
mbgl.on('message', function(msg) {
console.log('%s (%s): %s', msg.severity, msg.class, msg.text);
@@ -30,16 +33,17 @@ module.exports = function (style, options, callback) {
callback(new Error('timed out after 20 seconds'));
}, 20000);
- options.center = style.center;
- options.zoom = style.zoom;
- options.bearing = style.bearing;
- options.pitch = style.pitch;
options.debug = {
tileBorders: options.debug,
collision: options.collisionDebug,
overdraw: options.showOverdrawInspector,
};
+ options.center = style.center || [0, 0];
+ options.zoom = style.zoom || 0;
+ options.bearing = style.bearing || 0;
+ options.pitch = style.pitch || 0;
+
map.load(style);
applyOperations(options.operations, function() {
@@ -60,16 +64,32 @@ module.exports = function (style, options, callback) {
callback();
} else if (operation[0] === 'wait') {
- var wait = function() {
- if (map.loaded()) {
- applyOperations(operations.slice(1), callback);
- } else {
- map.render(options, wait);
- }
- };
- wait();
+ map.render(options, function () {
+ applyOperations(operations.slice(1), callback);
+ });
+
+ } else if (operation[0] === 'addImage') {
+ var img = PNG.sync.read(fs.readFileSync(path.join(__dirname, '../../../mapbox-gl-js/test/integration', operation[2])));
+ map.addImage(operation[1], img.data, {
+ height: img.height,
+ width: img.width,
+ pixelRatio: 1
+ });
+
+ applyOperations(operations.slice(1), callback);
} else {
+ // Ensure that the next `map.render(options)` does not overwrite this change.
+ if (operation[0] === 'setCenter') {
+ options.center = operation[1];
+ } else if (operation[0] === 'setZoom') {
+ options.zoom = operation[1];
+ } else if (operation[0] === 'setBearing') {
+ options.bearing = operation[1];
+ } else if (operation[0] === 'setPitch') {
+ options.pitch = operation[1];
+ }
+
map[operation[0]].apply(map, operation.slice(1));
applyOperations(operations.slice(1), callback);
}
diff --git a/platform/qt/app/mapwindow.cpp b/platform/qt/app/mapwindow.cpp
index e8e3a13489..0b453406f3 100644
--- a/platform/qt/app/mapwindow.cpp
+++ b/platform/qt/app/mapwindow.cpp
@@ -17,44 +17,30 @@ int kAnimationDuration = 10000;
MapWindow::MapWindow(const QMapboxGLSettings &settings)
- : m_map(nullptr, settings, size(), pixelRatio())
- , m_bearingAnimation(&m_map, "bearing")
- , m_zoomAnimation(&m_map, "zoom")
+ : m_settings(settings)
{
- connect(&m_map, SIGNAL(needsRendering()), this, SLOT(updateGL()));
-
- // Set default location to Helsinki.
- m_map.setCoordinateZoom(QMapbox::Coordinate(60.170448, 24.942046), 14);
-
- QString styleUrl = qgetenv("MAPBOX_STYLE_URL");
- if (styleUrl.isEmpty()) {
- changeStyle();
- } else {
- m_map.setStyleUrl(styleUrl);
- setWindowTitle(QString("Mapbox GL: ") + styleUrl);
- }
-
- connect(&m_zoomAnimation, SIGNAL(finished()), this, SLOT(animationFinished()));
- connect(&m_zoomAnimation, SIGNAL(valueChanged(const QVariant&)), this, SLOT(animationValueChanged()));
-
setWindowIcon(QIcon(":icon.png"));
}
void MapWindow::selfTest()
{
- m_bearingAnimation.setDuration(kAnimationDuration);
- m_bearingAnimation.setEndValue(m_map.bearing() + 360 * 4);
- m_bearingAnimation.start();
+ if (m_bearingAnimation) {
+ m_bearingAnimation->setDuration(kAnimationDuration);
+ m_bearingAnimation->setEndValue(m_map->bearing() + 360 * 4);
+ m_bearingAnimation->start();
+ }
- m_zoomAnimation.setDuration(kAnimationDuration);
- m_zoomAnimation.setEndValue(m_map.zoom() + 3);
- m_zoomAnimation.start();
+ if (m_zoomAnimation) {
+ m_zoomAnimation->setDuration(kAnimationDuration);
+ m_zoomAnimation->setEndValue(m_map->zoom() + 3);
+ m_zoomAnimation->start();
+ }
}
qreal MapWindow::pixelRatio() {
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
+#if QT_VERSION >= 0x050600
return devicePixelRatioF();
-#elif (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
+#elif QT_VERSION >= 0x050000
return devicePixelRatio();
#else
return 1;
@@ -81,7 +67,7 @@ void MapWindow::changeStyle()
auto& styles = QMapbox::defaultStyles();
- m_map.setStyleUrl(styles[currentStyleIndex].first);
+ m_map->setStyleUrl(styles[currentStyleIndex].first);
setWindowTitle(QString("Mapbox GL: ") + styles[currentStyleIndex].second);
if (++currentStyleIndex == styles.size()) {
@@ -93,7 +79,7 @@ void MapWindow::changeStyle()
void MapWindow::keyPressEvent(QKeyEvent *ev)
{
- static const QMapbox::TransitionOptions transition { 300, {} };
+ static const qint64 transitionDuration = 300;
switch (ev->key()) {
case Qt::Key_S:
@@ -106,88 +92,94 @@ void MapWindow::keyPressEvent(QKeyEvent *ev)
m_sourceAdded = true;
- QFile geojson(":source.geojson");
+ QFile geojson(":source1.geojson");
geojson.open(QIODevice::ReadOnly);
// The data source for the route line and markers
QVariantMap routeSource;
routeSource["type"] = "geojson";
routeSource["data"] = geojson.readAll();
- m_map.addSource("routeSource", routeSource);
+ m_map->addSource("routeSource", routeSource);
// The route case, painted before the route
QVariantMap routeCase;
routeCase["id"] = "routeCase";
routeCase["type"] = "line";
routeCase["source"] = "routeSource";
- m_map.addLayer(routeCase);
+ m_map->addLayer(routeCase);
- m_map.setPaintProperty("routeCase", "line-color", QColor("white"));
- m_map.setPaintProperty("routeCase", "line-width", 20.0);
- m_map.setLayoutProperty("routeCase", "line-join", "round");
- m_map.setLayoutProperty("routeCase", "line-cap", "round");
+ m_map->setPaintProperty("routeCase", "line-color", QColor("white"));
+ m_map->setPaintProperty("routeCase", "line-width", 20.0);
+ m_map->setLayoutProperty("routeCase", "line-join", "round");
+ m_map->setLayoutProperty("routeCase", "line-cap", "round");
// The route, painted on top of the route case
QVariantMap route;
route["id"] = "route";
route["type"] = "line";
route["source"] = "routeSource";
- m_map.addLayer(route);
+ m_map->addLayer(route);
+
+ m_map->setPaintProperty("route", "line-color", QColor("blue"));
+ m_map->setPaintProperty("route", "line-width", 8.0);
+ m_map->setLayoutProperty("route", "line-join", "round");
+ m_map->setLayoutProperty("route", "line-cap", "round");
- m_map.setPaintProperty("route", "line-color", QColor("blue"));
- m_map.setPaintProperty("route", "line-width", 8.0);
- m_map.setLayoutProperty("route", "line-join", "round");
- m_map.setLayoutProperty("route", "line-cap", "round");
+ QVariantList lineDashArray;
+ lineDashArray.append(1);
+ lineDashArray.append(2);
+
+ m_map->setPaintProperty("route", "line-dasharray", lineDashArray);
// Markers at the beginning and end of the route
- m_map.addImage("label-arrow", QImage(":label-arrow.svg"));
- m_map.addImage("label-background", QImage(":label-background.svg"));
+ m_map->addImage("label-arrow", QImage(":label-arrow.svg"));
+ m_map->addImage("label-background", QImage(":label-background.svg"));
- QVariantMap makerArrow;
- makerArrow["id"] = "makerArrow";
- makerArrow["type"] = "symbol";
- makerArrow["source"] = "routeSource";
- m_map.addLayer(makerArrow);
+ QVariantMap markerArrow;
+ markerArrow["id"] = "markerArrow";
+ markerArrow["type"] = "symbol";
+ markerArrow["source"] = "routeSource";
+ m_map->addLayer(markerArrow);
- m_map.setLayoutProperty("makerArrow", "icon-image", "label-arrow");
- m_map.setLayoutProperty("makerArrow", "icon-size", 0.5);
- m_map.setLayoutProperty("makerArrow", "icon-ignore-placement", true);
+ m_map->setLayoutProperty("markerArrow", "icon-image", "label-arrow");
+ m_map->setLayoutProperty("markerArrow", "icon-size", 0.5);
+ m_map->setLayoutProperty("markerArrow", "icon-ignore-placement", true);
QVariantList arrowOffset;
arrowOffset.append(0.0);
arrowOffset.append(-15.0);
- m_map.setLayoutProperty("makerArrow", "icon-offset", arrowOffset);
-
- QVariantMap makerBackground;
- makerBackground["id"] = "makerBackground";
- makerBackground["type"] = "symbol";
- makerBackground["source"] = "routeSource";
- m_map.addLayer(makerBackground);
-
- m_map.setLayoutProperty("makerBackground", "icon-image", "label-background");
- m_map.setLayoutProperty("makerBackground", "text-field", "{name}");
- m_map.setLayoutProperty("makerBackground", "icon-text-fit", "both");
- m_map.setLayoutProperty("makerBackground", "icon-ignore-placement", true);
- m_map.setLayoutProperty("makerBackground", "text-ignore-placement", true);
- m_map.setLayoutProperty("makerBackground", "text-anchor", "left");
- m_map.setLayoutProperty("makerBackground", "text-size", 16.0);
- m_map.setLayoutProperty("makerBackground", "text-padding", 0.0);
- m_map.setLayoutProperty("makerBackground", "text-line-height", 1.0);
- m_map.setLayoutProperty("makerBackground", "text-max-width", 8.0);
+ m_map->setLayoutProperty("markerArrow", "icon-offset", arrowOffset);
+
+ QVariantMap markerBackground;
+ markerBackground["id"] = "markerBackground";
+ markerBackground["type"] = "symbol";
+ markerBackground["source"] = "routeSource";
+ m_map->addLayer(markerBackground);
+
+ m_map->setLayoutProperty("markerBackground", "icon-image", "label-background");
+ m_map->setLayoutProperty("markerBackground", "text-field", "{name}");
+ m_map->setLayoutProperty("markerBackground", "icon-text-fit", "both");
+ m_map->setLayoutProperty("markerBackground", "icon-ignore-placement", true);
+ m_map->setLayoutProperty("markerBackground", "text-ignore-placement", true);
+ m_map->setLayoutProperty("markerBackground", "text-anchor", "left");
+ m_map->setLayoutProperty("markerBackground", "text-size", 16.0);
+ m_map->setLayoutProperty("markerBackground", "text-padding", 0.0);
+ m_map->setLayoutProperty("markerBackground", "text-line-height", 1.0);
+ m_map->setLayoutProperty("markerBackground", "text-max-width", 8.0);
QVariantList iconTextFitPadding;
iconTextFitPadding.append(15.0);
iconTextFitPadding.append(10.0);
iconTextFitPadding.append(15.0);
iconTextFitPadding.append(10.0);
- m_map.setLayoutProperty("makerBackground", "icon-text-fit-padding", iconTextFitPadding);
+ m_map->setLayoutProperty("markerBackground", "icon-text-fit-padding", iconTextFitPadding);
QVariantList backgroundOffset;
backgroundOffset.append(-0.5);
backgroundOffset.append(-1.5);
- m_map.setLayoutProperty("makerBackground", "text-offset", backgroundOffset);
+ m_map->setLayoutProperty("markerBackground", "text-offset", backgroundOffset);
- m_map.setPaintProperty("makerBackground", "text-color", QColor("white"));
+ m_map->setPaintProperty("markerBackground", "text-color", QColor("white"));
QVariantList filterExpression;
filterExpression.append("==");
@@ -197,29 +189,29 @@ void MapWindow::keyPressEvent(QKeyEvent *ev)
QVariantList filter;
filter.append(filterExpression);
- m_map.setFilter("makerArrow", filter);
- m_map.setFilter("makerBackground", filter);
+ m_map->setFilter("markerArrow", filter);
+ m_map->setFilter("markerBackground", filter);
// Tilt the labels when tilting the map and make them larger
- m_map.setLayoutProperty("road-label-large", "text-size", 30.0);
- m_map.setLayoutProperty("road-label-large", "text-pitch-alignment", "viewport");
+ m_map->setLayoutProperty("road-label-large", "text-size", 30.0);
+ m_map->setLayoutProperty("road-label-large", "text-pitch-alignment", "viewport");
- m_map.setLayoutProperty("road-label-medium", "text-size", 30.0);
- m_map.setLayoutProperty("road-label-medium", "text-pitch-alignment", "viewport");
+ m_map->setLayoutProperty("road-label-medium", "text-size", 30.0);
+ m_map->setLayoutProperty("road-label-medium", "text-pitch-alignment", "viewport");
- m_map.setLayoutProperty("road-label-small", "text-pitch-alignment", "viewport");
- m_map.setLayoutProperty("road-label-small", "text-size", 30.0);
+ m_map->setLayoutProperty("road-label-small", "text-pitch-alignment", "viewport");
+ m_map->setLayoutProperty("road-label-small", "text-size", 30.0);
}
break;
case Qt::Key_Tab:
- m_map.cycleDebugOptions();
+ m_map->cycleDebugOptions();
break;
case Qt::Key_R: {
- m_map.setTransitionOptions(transition);
- if (m_map.hasClass("night")) {
- m_map.removeClass("night");
+ m_map->setTransitionOptions(transitionDuration);
+ if (m_map->hasClass("night")) {
+ m_map->removeClass("night");
} else {
- m_map.addClass("night");
+ m_map->addClass("night");
}
} break;
default:
@@ -245,9 +237,9 @@ void MapWindow::mousePressEvent(QMouseEvent *ev)
if (ev->type() == QEvent::MouseButtonDblClick) {
if (ev->buttons() == Qt::LeftButton) {
- m_map.scaleBy(2.0, m_lastPos);
+ m_map->scaleBy(2.0, m_lastPos);
} else if (ev->buttons() == Qt::RightButton) {
- m_map.scaleBy(0.5, m_lastPos);
+ m_map->scaleBy(0.5, m_lastPos);
}
}
@@ -264,14 +256,14 @@ void MapWindow::mouseMoveEvent(QMouseEvent *ev)
if (!delta.isNull()) {
if (ev->buttons() == Qt::LeftButton && ev->modifiers() & Qt::ShiftModifier) {
- m_map.setPitch(m_map.pitch() - delta.y());
+ m_map->setPitch(m_map->pitch() - delta.y());
} else if (ev->buttons() == Qt::LeftButton) {
- m_map.moveBy(delta);
+ m_map->moveBy(delta);
} else if (ev->buttons() == Qt::RightButton) {
#if QT_VERSION < 0x050000
- m_map.rotateBy(m_lastPos, ev->posF());
+ m_map->rotateBy(m_lastPos, ev->posF());
#else
- m_map.rotateBy(m_lastPos, ev->localPos());
+ m_map->rotateBy(m_lastPos, ev->localPos());
#endif
}
}
@@ -295,29 +287,38 @@ void MapWindow::wheelEvent(QWheelEvent *ev)
factor = factor > -1 ? factor : 1 / factor;
}
- m_map.scaleBy(1 + factor, ev->pos());
+ m_map->scaleBy(1 + factor, ev->pos());
ev->accept();
}
void MapWindow::initializeGL()
{
QMapbox::initializeGLExtensions();
+
+ m_map.reset(new QMapboxGL(nullptr, m_settings, size(), pixelRatio()));
+ connect(m_map.data(), SIGNAL(needsRendering()), this, SLOT(update()));
+
+ // Set default location to Helsinki.
+ m_map->setCoordinateZoom(QMapbox::Coordinate(60.170448, 24.942046), 14);
+
+ QString styleUrl = qgetenv("MAPBOX_STYLE_URL");
+ if (styleUrl.isEmpty()) {
+ changeStyle();
+ } else {
+ m_map->setStyleUrl(styleUrl);
+ setWindowTitle(QString("Mapbox GL: ") + styleUrl);
+ }
+
+ m_bearingAnimation = new QPropertyAnimation(m_map.data(), "bearing");
+ m_zoomAnimation = new QPropertyAnimation(m_map.data(), "zoom");
+
+ connect(m_zoomAnimation, SIGNAL(finished()), this, SLOT(animationFinished()));
+ connect(m_zoomAnimation, SIGNAL(valueChanged(const QVariant&)), this, SLOT(animationValueChanged()));
}
void MapWindow::paintGL()
{
m_frameDraws++;
-
- m_map.resize(size(), size() * pixelRatio());
-
-#if QT_VERSION < 0x050400 && defined(__APPLE__)
- // XXX GL framebuffer is valid only after first attempt of painting on
- // older versions of Qt on macOS.
- // See https://bugreports.qt.io/browse/QTBUG-36802 for details.
- static bool first = true;
- if (!first) m_map.render();
- first = false;
-#else
- m_map.render();
-#endif
+ m_map->resize(size(), size() * pixelRatio());
+ m_map->render();
}
diff --git a/platform/qt/app/mapwindow.hpp b/platform/qt/app/mapwindow.hpp
index a579a5bcc5..23880902d3 100644
--- a/platform/qt/app/mapwindow.hpp
+++ b/platform/qt/app/mapwindow.hpp
@@ -1,15 +1,29 @@
#ifndef MAPWINDOW_H
#define MAPWINDOW_H
-#include <QGLWidget>
#include <QMapboxGL>
+
+#include <QtGlobal>
+
+// XXX http://stackoverflow.com/questions/24899558/how-to-check-qt-version-to-include-different-header#comment59591604_29887388
+#if QT_VERSION >= 0x050400
+#include <QOpenGLWidget>
+#else
+#include <QGLWidget>
+#endif // QT_VERSION
+
#include <QPropertyAnimation>
+#include <QScopedPointer>
class QKeyEvent;
class QMouseEvent;
class QWheelEvent;
+#if QT_VERSION >= 0x050400
+class MapWindow : public QOpenGLWidget
+#else
class MapWindow : public QGLWidget
+#endif // QT_VERSION
{
Q_OBJECT
@@ -26,21 +40,23 @@ private:
void changeStyle();
qreal pixelRatio();
- // QGLWidget implementation.
+ // QWidget implementation.
void keyPressEvent(QKeyEvent *ev) final;
void mousePressEvent(QMouseEvent *ev) final;
void mouseMoveEvent(QMouseEvent *ev) final;
void wheelEvent(QWheelEvent *ev) final;
+ // Q{,Open}GLWidget implementation.
void initializeGL() final;
void paintGL() final;
QPointF m_lastPos;
- QMapboxGL m_map;
+ QMapboxGLSettings m_settings;
+ QScopedPointer<QMapboxGL> m_map;
- QPropertyAnimation m_bearingAnimation;
- QPropertyAnimation m_zoomAnimation;
+ QPropertyAnimation *m_bearingAnimation;
+ QPropertyAnimation *m_zoomAnimation;
unsigned m_animationTicks = 0;
unsigned m_frameDraws = 0;
diff --git a/platform/qt/config.cmake b/platform/qt/config.cmake
index ff86a0dee1..f2beedcfa2 100644
--- a/platform/qt/config.cmake
+++ b/platform/qt/config.cmake
@@ -9,13 +9,17 @@ if(NOT WITH_QT_DECODERS)
mason_use(webp VERSION 0.5.1)
endif()
+if(NOT WITH_QT_I18N)
+ mason_use(icu VERSION 58.1)
+endif()
+
macro(mbgl_platform_core)
target_sources(mbgl-core
${MBGL_QT_FILES}
)
target_include_directories(mbgl-core
- PRIVATE platform/default
+ PUBLIC platform/default
PRIVATE platform/qt/include
)
@@ -38,16 +42,27 @@ macro(mbgl_platform_core)
else()
add_definitions(-DQT_IMAGE_DECODERS)
endif()
+
+ if(NOT WITH_QT_I18N)
+ target_sources(mbgl-core PRIVATE platform/default/bidi.cpp)
+ target_add_mason_package(mbgl-core PRIVATE icu)
+ else()
+ target_sources(mbgl-core PRIVATE platform/qt/src/bidi.cpp)
+ endif()
+
endmacro()
macro(mbgl_platform_test)
target_sources(mbgl-test
PRIVATE test/src/main.cpp
- PRIVATE platform/qt/test/headless_backend_qt.cpp
PRIVATE platform/qt/test/qmapboxgl.cpp
- PRIVATE platform/default/headless_backend.cpp
- PRIVATE platform/default/headless_display.cpp
- PRIVATE platform/default/offscreen_view.cpp
+ PRIVATE platform/default/mbgl/gl/headless_backend.cpp
+ PRIVATE platform/default/mbgl/gl/headless_backend.hpp
+ PRIVATE platform/default/mbgl/gl/headless_display.cpp
+ PRIVATE platform/default/mbgl/gl/headless_display.hpp
+ PRIVATE platform/default/mbgl/gl/offscreen_view.cpp
+ PRIVATE platform/default/mbgl/gl/offscreen_view.hpp
+ PRIVATE platform/qt/test/headless_backend_qt.cpp
)
set_source_files_properties(
diff --git a/platform/qt/config.qdocconf b/platform/qt/config.qdocconf
index 1af76430f8..7dbe6423eb 100644
--- a/platform/qt/config.qdocconf
+++ b/platform/qt/config.qdocconf
@@ -12,4 +12,5 @@ headerdirs += include
sourcedirs += src
indexes = $QT_INSTALL_DOCS/qtcore/qtcore.index \
+ $QT_INSTALL_DOCS/qtgui/qtgui.index \
$QT_INSTALL_DOCS/qtnetwork/qtnetwork.index
diff --git a/platform/qt/include/qmapbox.hpp b/platform/qt/include/qmapbox.hpp
index 9de4a7041d..b2e3b521d0 100644
--- a/platform/qt/include/qmapbox.hpp
+++ b/platform/qt/include/qmapbox.hpp
@@ -29,34 +29,6 @@ enum NetworkMode {
Offline,
};
-// Reflects mbgl::MapChange.
-enum MapChange {
- MapChangeRegionWillChange = 0,
- MapChangeRegionWillChangeAnimated,
- MapChangeRegionIsChanging,
- MapChangeRegionDidChange,
- MapChangeRegionDidChangeAnimated,
- MapChangeWillStartLoadingMap,
- MapChangeDidFinishLoadingMap,
- MapChangeDidFailLoadingMap,
- MapChangeWillStartRenderingFrame,
- MapChangeDidFinishRenderingFrame,
- MapChangeDidFinishRenderingFrameFullyRendered,
- MapChangeWillStartRenderingMap,
- MapChangeDidFinishRenderingMap,
- MapChangeDidFinishRenderingMapFullyRendered,
- MapChangeDidFinishLoadingStyle,
- MapChangeSourceDidChange
-};
-
-struct Q_DECL_EXPORT CameraOptions {
- QVariant center; // Coordinate
- QVariant anchor; // QPointF
- QVariant zoom; // double
- QVariant angle; // double
- QVariant pitch; // double
-};
-
Q_DECL_EXPORT QList<QPair<QString, QString> >& defaultStyles();
Q_DECL_EXPORT NetworkMode networkMode();
@@ -74,11 +46,6 @@ struct Q_DECL_EXPORT CustomLayerRenderParameters {
double altitude;
};
-struct Q_DECL_EXPORT TransitionOptions {
- QVariant duration; // qint64
- QVariant delay; // qint64
-};
-
typedef void (*CustomLayerInitializeFunction)(void* context) ;
typedef void (*CustomLayerRenderFunction)(void* context, const CustomLayerRenderParameters&);
typedef void (*CustomLayerDeinitializeFunction)(void* context);
@@ -89,6 +56,5 @@ Q_DECL_EXPORT void registerTypes();
} // namespace QMapbox
Q_DECLARE_METATYPE(QMapbox::Coordinate);
-Q_DECLARE_METATYPE(QMapbox::MapChange);
#endif // QMAPBOX_H
diff --git a/platform/qt/include/qmapboxgl.hpp b/platform/qt/include/qmapboxgl.hpp
index d3937ce083..086601af25 100644
--- a/platform/qt/include/qmapboxgl.hpp
+++ b/platform/qt/include/qmapboxgl.hpp
@@ -2,9 +2,10 @@
#define QMAPBOXGL_H
#include <QMapbox>
+#include <QMargins>
#include <QObject>
-#include <QSize>
#include <QPointF>
+#include <QSize>
class QImage;
class QMargins;
@@ -22,11 +23,6 @@ class Q_DECL_EXPORT QMapboxGLSettings
public:
QMapboxGLSettings();
- enum MapMode {
- ContinuousMap = 0,
- StillMap
- };
-
enum GLContextMode {
UniqueGLContext = 0,
SharedGLContext
@@ -43,9 +39,6 @@ public:
FlippedYViewport
};
- MapMode mapMode() const;
- void setMapMode(MapMode);
-
GLContextMode contextMode() const;
void setContextMode(GLContextMode);
@@ -67,8 +60,10 @@ public:
QString accessToken() const;
void setAccessToken(const QString &);
+ QString apiBaseUrl() const;
+ void setApiBaseUrl(const QString &);
+
private:
- MapMode m_mapMode;
GLContextMode m_contextMode;
ConstrainMode m_constrainMode;
ViewportMode m_viewportMode;
@@ -77,6 +72,15 @@ private:
QString m_cacheDatabasePath;
QString m_assetPath;
QString m_accessToken;
+ QString m_apiBaseUrl;
+};
+
+struct Q_DECL_EXPORT QMapboxGLCameraOptions {
+ QVariant center; // Coordinate
+ QVariant anchor; // QPointF
+ QVariant zoom; // double
+ QVariant angle; // double
+ QVariant pitch; // double
};
class Q_DECL_EXPORT QMapboxGL : public QObject
@@ -87,8 +91,33 @@ class Q_DECL_EXPORT QMapboxGL : public QObject
Q_PROPERTY(double zoom READ zoom WRITE setZoom)
Q_PROPERTY(double bearing READ bearing WRITE setBearing)
Q_PROPERTY(double pitch READ pitch WRITE setPitch)
+ Q_PROPERTY(QString styleJson READ styleJson WRITE setStyleJson)
+ Q_PROPERTY(QString styleUrl READ styleUrl WRITE setStyleUrl)
+ Q_PROPERTY(double scale READ scale WRITE setScale)
+ Q_PROPERTY(QMapbox::Coordinate coordinate READ coordinate WRITE setCoordinate)
+ Q_PROPERTY(QMargins margins READ margins WRITE setMargins)
public:
+ // Reflects mbgl::MapChange.
+ enum MapChange {
+ MapChangeRegionWillChange = 0,
+ MapChangeRegionWillChangeAnimated,
+ MapChangeRegionIsChanging,
+ MapChangeRegionDidChange,
+ MapChangeRegionDidChangeAnimated,
+ MapChangeWillStartLoadingMap,
+ MapChangeDidFinishLoadingMap,
+ MapChangeDidFailLoadingMap,
+ MapChangeWillStartRenderingFrame,
+ MapChangeDidFinishRenderingFrame,
+ MapChangeDidFinishRenderingFrameFullyRendered,
+ MapChangeWillStartRenderingMap,
+ MapChangeDidFinishRenderingMap,
+ MapChangeDidFinishRenderingMapFullyRendered,
+ MapChangeDidFinishLoadingStyle,
+ MapChangeSourceDidChange
+ };
+
// Determines the orientation of the map.
enum NorthOrientation {
NorthUpwards, // Default
@@ -140,7 +169,7 @@ public:
void setCoordinate(const QMapbox::Coordinate &);
void setCoordinateZoom(const QMapbox::Coordinate &, double zoom);
- void jumpTo(const QMapbox::CameraOptions&);
+ void jumpTo(const QMapboxGLCameraOptions&);
void setGestureInProgress(bool inProgress);
@@ -150,8 +179,9 @@ public:
void setClasses(const QStringList &);
QStringList getClasses() const;
- QMapbox::TransitionOptions getTransitionOptions() const;
- void setTransitionOptions(const QMapbox::TransitionOptions&);
+ void setTransitionOptions(qint64 duration, qint64 delay = 0);
+
+ void addAnnotationIcon(const QString &name, const QImage &sprite);
QMapbox::AnnotationID addPointAnnotation(const QMapbox::PointAnnotation &);
QMapbox::AnnotationID addShapeAnnotation(const QMapbox::ShapeAnnotation &);
@@ -163,9 +193,6 @@ public:
void setLayoutProperty(const QString &layer, const QString &property, const QVariant &value);
void setPaintProperty(const QString &layer, const QString &property, const QVariant &value, const QString &klass = QString());
- bool isRotating() const;
- bool isScaling() const;
- bool isPanning() const;
bool isFullyLoaded() const;
void moveBy(const QPointF &offset);
@@ -174,8 +201,6 @@ public:
void resize(const QSize &size, const QSize &framebufferSize);
- void addAnnotationIcon(const QString &name, const QImage &sprite);
-
QPointF pixelForCoordinate(const QMapbox::Coordinate &) const;
QMapbox::Coordinate coordinateForPixel(const QPointF &) const;
@@ -186,6 +211,7 @@ public:
QMargins margins() const;
void addSource(const QString &sourceID, const QVariantMap& params);
+ void updateSource(const QString &sourceID, const QVariantMap& params);
void removeSource(const QString &sourceID);
void addImage(const QString &name, const QImage &sprite);
@@ -212,7 +238,8 @@ public slots:
signals:
void needsRendering();
- void mapChanged(QMapbox::MapChange);
+ void mapChanged(QMapboxGL::MapChange);
+ void copyrightsChanged(const QString &copyrightsHtml);
private:
Q_DISABLE_COPY(QMapboxGL)
@@ -220,4 +247,6 @@ private:
QMapboxGLPrivate *d_ptr;
};
+Q_DECLARE_METATYPE(QMapboxGL::MapChange);
+
#endif // QMAPBOXGL_H
diff --git a/platform/qt/qmlapp/main.qml b/platform/qt/qmlapp/main.qml
index fa157333d0..fd62193b42 100644
--- a/platform/qt/qmlapp/main.qml
+++ b/platform/qt/qmlapp/main.qml
@@ -30,10 +30,11 @@ ApplicationWindow {
property var fillColor: waterColorDialog.color
},
MapParameter {
+ id: source
property var type: "source"
property var name: "routeSource"
property var sourceType: "geojson"
- property var data: ":source.geojson"
+ property var data: ":source1.geojson"
},
MapParameter {
property var type: "layer"
@@ -256,11 +257,11 @@ ApplicationWindow {
title: "Style:"
ColumnLayout {
- ExclusiveGroup { id: group }
+ ExclusiveGroup { id: styleGroup }
RadioButton {
text: "Streets"
checked: true
- exclusiveGroup: group
+ exclusiveGroup: styleGroup
onClicked: {
style.url = "mapbox://styles/mapbox/streets-v9"
landColorDialog.color = "#e0ded8"
@@ -269,7 +270,7 @@ ApplicationWindow {
}
RadioButton {
text: "Dark"
- exclusiveGroup: group
+ exclusiveGroup: styleGroup
onClicked: {
style.url = "mapbox://styles/mapbox/dark-v9"
landColorDialog.color = "#343332"
@@ -278,7 +279,7 @@ ApplicationWindow {
}
RadioButton {
text: "Satellite"
- exclusiveGroup: group
+ exclusiveGroup: styleGroup
onClicked: {
style.url = "mapbox://styles/mapbox/satellite-v9"
}
@@ -300,6 +301,41 @@ ApplicationWindow {
onClicked: waterColorDialog.open()
}
+ GroupBox {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ title: "Route:"
+
+ ColumnLayout {
+ ExclusiveGroup { id: sourceGroup }
+ RadioButton {
+ text: "Route 1"
+ checked: true
+ exclusiveGroup: sourceGroup
+ onClicked: {
+ source.data = ":source1.geojson"
+ }
+ }
+ RadioButton {
+ text: "Route 2"
+ exclusiveGroup: sourceGroup
+ onClicked: {
+ source.data = ":source2.geojson"
+ }
+ }
+ RadioButton {
+ text: "Route 3"
+ exclusiveGroup: sourceGroup
+ onClicked: {
+ source.data = '{ "type": "FeatureCollection", "features": \
+ [{ "type": "Feature", "properties": {}, "geometry": { \
+ "type": "LineString", "coordinates": [[ 24.934938848018646, \
+ 60.16830257086771 ], [ 24.943315386772156, 60.16227776476442 ]]}}]}'
+ }
+ }
+ }
+ }
+
CheckBox {
id: toggleRoute
anchors.left: parent.left
diff --git a/platform/qt/qt.cmake b/platform/qt/qt.cmake
index 398e173cfa..3382a9ac6b 100644
--- a/platform/qt/qt.cmake
+++ b/platform/qt/qt.cmake
@@ -2,6 +2,7 @@
# support `mason` (i.e. Yocto). Do not add any `mason` macro.
option(WITH_QT_DECODERS "Use builtin Qt image decoders" OFF)
+option(WITH_QT_I18N "Use builtin Qt i18n support" OFF)
option(WITH_QT_4 "Use Qt4 instead of Qt5" OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -D__QT__")
@@ -28,10 +29,11 @@ set(MBGL_QT_FILES
PRIVATE platform/default/sqlite3.hpp
# Misc
- PRIVATE platform/default/log_stderr.cpp
+ PRIVATE platform/default/logging_stderr.cpp
# Thread pool
- PRIVATE platform/default/thread_pool.cpp
+ PRIVATE platform/default/mbgl/util/default_thread_pool.cpp
+ PRIVATE platform/default/mbgl/util/default_thread_pool.cpp
# Platform integration
PRIVATE platform/qt/src/async_task.cpp
@@ -59,6 +61,8 @@ add_library(qmapboxgl SHARED
platform/qt/src/qmapbox.cpp
platform/qt/src/qmapboxgl.cpp
platform/qt/src/qmapboxgl_p.hpp
+ platform/default/mbgl/util/default_styles.hpp
+ platform/default/mbgl/util/default_styles.cpp
)
# C++ app
@@ -76,7 +80,7 @@ else()
endif()
# OS specific configurations
-if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
+if (MASON_PLATFORM STREQUAL "osx" OR MASON_PLATFORM STREQUAL "ios")
list(APPEND MBGL_QT_FILES
PRIVATE platform/darwin/src/nsthread.mm
)
@@ -92,3 +96,11 @@ else()
PRIVATE -lGL
)
endif()
+
+add_custom_command(
+ TARGET qmapboxgl
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ ${CMAKE_SOURCE_DIR}/platform/qt/include
+ ${CMAKE_CURRENT_BINARY_DIR}/platform/qt/include
+)
diff --git a/platform/qt/resources/common.qrc b/platform/qt/resources/common.qrc
index e9fd46cfa7..9d409760cc 100644
--- a/platform/qt/resources/common.qrc
+++ b/platform/qt/resources/common.qrc
@@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/">
- <file>source.geojson</file>
+ <file>source1.geojson</file>
+ <file>source2.geojson</file>
<file>label-arrow.svg</file>
<file>label-background.svg</file>
</qresource>
diff --git a/platform/qt/resources/source.geojson b/platform/qt/resources/source1.geojson
index 1d270ba189..1d270ba189 100644
--- a/platform/qt/resources/source.geojson
+++ b/platform/qt/resources/source1.geojson
diff --git a/platform/qt/resources/source2.geojson b/platform/qt/resources/source2.geojson
new file mode 100644
index 0000000000..df300d1040
--- /dev/null
+++ b/platform/qt/resources/source2.geojson
@@ -0,0 +1,92 @@
+{
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "type": "Feature",
+ "properties": {
+ "type": "label",
+ "name": "Start"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 24.943320751190186,
+ 60.166471893909794
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {
+ "type": "label",
+ "name": "End"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 24.942440986633297,
+ 60.16715507391703
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {
+ "type": "label",
+ "name": "Traffic Accident"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 24.94018793106079,
+ 60.16696293097573
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [
+ 24.943320751190186,
+ 60.166471893909794
+ ],
+ [
+ 24.934544563293453,
+ 60.16347213858629
+ ],
+ [
+ 24.93321418762207,
+ 60.16446497048834
+ ],
+ [
+ 24.94018793106079,
+ 60.16696293097573
+ ],
+ [
+ 24.93875026702881,
+ 60.16806240040351
+ ],
+ [
+ 24.937891960144043,
+ 60.16777419352904
+ ],
+ [
+ 24.936089515686035,
+ 60.169033745694826
+ ],
+ [
+ 24.9384069442749,
+ 60.16984495711831
+ ],
+ [
+ 24.942440986633297,
+ 60.16715507391703
+ ]
+ ]
+ }
+ }
+ ]
+}
diff --git a/platform/qt/scripts/toolchain.sh b/platform/qt/scripts/toolchain.sh
deleted file mode 100755
index bb08e0b010..0000000000
--- a/platform/qt/scripts/toolchain.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -o pipefail
-
-if [ -z ${MASON_SYSROOT:-} ]; then
- exit 0
-fi
-
-export PATH="`pwd`/.mason:${PATH}"
-export MASON_DIR="`pwd`/.mason"
-
-export PATH=`mason env PATH`
-
-echo CXX=\"`which $(mason env CXX)`\"
-echo CC=\"`which $(mason env CC)`\"
-echo LD=\"`which $(mason env LD)`\"
-echo LINK=\"`which $(mason env CXX)`\"
-echo AR=\"`which $(mason env AR)`\"
-echo RANLIB=\"`which $(mason env RANLIB)`\"
-echo STRIP=\"`which $(mason env STRIP)`\"
diff --git a/platform/qt/src/bidi.cpp b/platform/qt/src/bidi.cpp
new file mode 100644
index 0000000000..0eaeb3f2f4
--- /dev/null
+++ b/platform/qt/src/bidi.cpp
@@ -0,0 +1,52 @@
+#include <memory>
+
+#include <mbgl/text/bidi.hpp>
+
+#include <QString>
+
+namespace mbgl {
+
+class BiDiImpl {
+public:
+ QString string;
+};
+
+std::u16string applyArabicShaping(const std::u16string& input) {
+ QString utf16string = QString::fromStdU16String(input);
+ return utf16string.toStdU16String();
+}
+
+void BiDi::mergeParagraphLineBreaks(std::set<std::size_t>& lineBreakPoints) {
+ lineBreakPoints.insert(static_cast<std::size_t>(bidi.impl->string.length()));
+}
+
+std::vector<std::u16string>
+BiDi::applyLineBreaking(std::set<std::size_t> lineBreakPoints) {
+ mergeParagraphLineBreaks(lineBreakPoints);
+
+ std::vector<std::u16string> transformedLines;
+ std::size_t start = 0;
+ for (std::size_t lineBreakPoint : lineBreakPoints) {
+ transformedLines.push_back(bidi.getLine(start, lineBreakPoint));
+ start = lineBreakPoint;
+ }
+
+ return transformedLines;
+}
+
+BiDi::BiDi() : impl(std::make_unique<BiDiImpl>())
+{
+}
+
+BiDi::~BiDi() = default;
+
+std::vector<std::u16string> BiDi::processText(const std::u16string& input, std::set<std::size_t> lineBreakPoints) {
+ impl->string = QString::fromStdU16String(input);
+ return applyLineBreaking(lineBreakPoints);
+}
+
+std::u16string BiDi::getLine(std::size_t start, std::size_t end) {
+ return impl->string.mid(static_cast<int32_t>(start), static_cast<int32_t>(end - start)).toStdU16String();
+}
+
+} // end namespace mbgl
diff --git a/platform/qt/src/http_file_source.cpp b/platform/qt/src/http_file_source.cpp
index 61fa1ca612..9bf2cc5fac 100644
--- a/platform/qt/src/http_file_source.cpp
+++ b/platform/qt/src/http_file_source.cpp
@@ -1,7 +1,7 @@
#include "http_file_source.hpp"
#include "http_request.hpp"
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <QByteArray>
#include <QDir>
diff --git a/platform/qt/src/image.cpp b/platform/qt/src/image.cpp
index 3918b35208..403ca9cbd3 100644
--- a/platform/qt/src/image.cpp
+++ b/platform/qt/src/image.cpp
@@ -7,7 +7,7 @@
namespace mbgl {
std::string encodePNG(const PremultipliedImage& pre) {
- QImage image(pre.data.get(), pre.width, pre.height,
+ QImage image(pre.data.get(), pre.size.width, pre.size.height,
QImage::Format_ARGB32_Premultiplied);
QByteArray array;
@@ -57,7 +57,7 @@ PremultipliedImage decodeImage(const std::string& string) {
auto img = std::make_unique<uint8_t[]>(image.byteCount());
memcpy(img.get(), image.constBits(), image.byteCount());
- return { static_cast<uint16_t>(image.width()), static_cast<uint16_t>(image.height()),
+ return { { static_cast<uint32_t>(image.width()), static_cast<uint32_t>(image.height()) },
std::move(img) };
}
}
diff --git a/platform/qt/src/qmapbox.cpp b/platform/qt/src/qmapbox.cpp
index 118b1355e2..379b0cdd57 100644
--- a/platform/qt/src/qmapbox.cpp
+++ b/platform/qt/src/qmapbox.cpp
@@ -18,24 +18,6 @@
static_assert(mbgl::underlying_type(QMapbox::Online) == mbgl::underlying_type(mbgl::NetworkStatus::Status::Online), "error");
static_assert(mbgl::underlying_type(QMapbox::Offline) == mbgl::underlying_type(mbgl::NetworkStatus::Status::Offline), "error");
-// mbgl::MapChange
-static_assert(mbgl::underlying_type(QMapbox::MapChangeRegionWillChange) == mbgl::underlying_type(mbgl::MapChangeRegionWillChange), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeRegionWillChangeAnimated) == mbgl::underlying_type(mbgl::MapChangeRegionWillChangeAnimated), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeRegionIsChanging) == mbgl::underlying_type(mbgl::MapChangeRegionIsChanging), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeRegionDidChange) == mbgl::underlying_type(mbgl::MapChangeRegionDidChange), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeRegionDidChangeAnimated) == mbgl::underlying_type(mbgl::MapChangeRegionDidChangeAnimated), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeWillStartLoadingMap) == mbgl::underlying_type(mbgl::MapChangeWillStartLoadingMap), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeDidFinishLoadingMap) == mbgl::underlying_type(mbgl::MapChangeDidFinishLoadingMap), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeDidFailLoadingMap) == mbgl::underlying_type(mbgl::MapChangeDidFailLoadingMap), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeWillStartRenderingFrame) == mbgl::underlying_type(mbgl::MapChangeWillStartRenderingFrame), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeDidFinishRenderingFrame) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingFrame), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeDidFinishRenderingFrameFullyRendered) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingFrameFullyRendered), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeWillStartRenderingMap) == mbgl::underlying_type(mbgl::MapChangeWillStartRenderingMap), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeDidFinishRenderingMap) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingMap), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeDidFinishRenderingMapFullyRendered) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingMapFullyRendered), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeDidFinishLoadingStyle) == mbgl::underlying_type(mbgl::MapChangeDidFinishLoadingStyle), "error");
-static_assert(mbgl::underlying_type(QMapbox::MapChangeSourceDidChange) == mbgl::underlying_type(mbgl::MapChangeSourceDidChange), "error");
-
namespace QMapbox {
Q_DECL_EXPORT NetworkMode networkMode()
diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp
index edda1f9599..86604a945f 100644
--- a/platform/qt/src/qmapboxgl.cpp
+++ b/platform/qt/src/qmapboxgl.cpp
@@ -13,6 +13,7 @@
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/source.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
+#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/transition_options.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/storage/network_status.hpp>
@@ -25,6 +26,7 @@
#include <QGuiApplication>
#include <QWindow>
#include <QOpenGLFramebufferObject>
+#include <QOpenGLContext>
#else
#include <QCoreApplication>
#endif
@@ -40,10 +42,6 @@
using namespace QMapbox;
-// mbgl::MapMode
-static_assert(mbgl::underlying_type(QMapboxGLSettings::ContinuousMap) == mbgl::underlying_type(mbgl::MapMode::Continuous), "error");
-static_assert(mbgl::underlying_type(QMapboxGLSettings::StillMap) == mbgl::underlying_type(mbgl::MapMode::Still), "error");
-
// mbgl::GLContextMode
static_assert(mbgl::underlying_type(QMapboxGLSettings::UniqueGLContext) == mbgl::underlying_type(mbgl::GLContextMode::Unique), "error");
static_assert(mbgl::underlying_type(QMapboxGLSettings::SharedGLContext) == mbgl::underlying_type(mbgl::GLContextMode::Shared), "error");
@@ -57,6 +55,24 @@ static_assert(mbgl::underlying_type(QMapboxGLSettings::ConstrainWidthAndHeight)
static_assert(mbgl::underlying_type(QMapboxGLSettings::DefaultViewport) == mbgl::underlying_type(mbgl::ViewportMode::Default), "error");
static_assert(mbgl::underlying_type(QMapboxGLSettings::FlippedYViewport) == mbgl::underlying_type(mbgl::ViewportMode::FlippedY), "error");
+// mbgl::MapChange
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeRegionWillChange) == mbgl::underlying_type(mbgl::MapChangeRegionWillChange), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeRegionWillChangeAnimated) == mbgl::underlying_type(mbgl::MapChangeRegionWillChangeAnimated), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeRegionIsChanging) == mbgl::underlying_type(mbgl::MapChangeRegionIsChanging), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeRegionDidChange) == mbgl::underlying_type(mbgl::MapChangeRegionDidChange), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeRegionDidChangeAnimated) == mbgl::underlying_type(mbgl::MapChangeRegionDidChangeAnimated), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeWillStartLoadingMap) == mbgl::underlying_type(mbgl::MapChangeWillStartLoadingMap), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishLoadingMap) == mbgl::underlying_type(mbgl::MapChangeDidFinishLoadingMap), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFailLoadingMap) == mbgl::underlying_type(mbgl::MapChangeDidFailLoadingMap), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeWillStartRenderingFrame) == mbgl::underlying_type(mbgl::MapChangeWillStartRenderingFrame), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishRenderingFrame) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingFrame), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishRenderingFrameFullyRendered) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingFrameFullyRendered), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeWillStartRenderingMap) == mbgl::underlying_type(mbgl::MapChangeWillStartRenderingMap), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishRenderingMap) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingMap), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishRenderingMapFullyRendered) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingMapFullyRendered), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishLoadingStyle) == mbgl::underlying_type(mbgl::MapChangeDidFinishLoadingStyle), "error");
+static_assert(mbgl::underlying_type(QMapboxGL::MapChangeSourceDidChange) == mbgl::underlying_type(mbgl::MapChangeSourceDidChange), "error");
+
// mbgl::NorthOrientation
static_assert(mbgl::underlying_type(QMapboxGL::NorthUpwards) == mbgl::underlying_type(mbgl::NorthOrientation::Upwards), "error");
static_assert(mbgl::underlying_type(QMapboxGL::NorthRightwards) == mbgl::underlying_type(mbgl::NorthOrientation::Rightwards), "error");
@@ -67,7 +83,7 @@ namespace {
QThreadStorage<std::shared_ptr<mbgl::util::RunLoop>> loop;
-// Convertion helper functions.
+// Conversion helper functions.
auto fromQMapboxGLShapeAnnotation(const ShapeAnnotation &shapeAnnotation) {
const LineString &lineString = shapeAnnotation.first;
@@ -83,26 +99,6 @@ auto fromQMapboxGLShapeAnnotation(const ShapeAnnotation &shapeAnnotation) {
return mbgl::StyleSourcedAnnotation { std::move(mbglLineString), styleLayer.toStdString() };
}
-auto fromQMapboxTransitionOptions(const QMapbox::TransitionOptions &options) {
- auto convert = [](auto& value) -> mbgl::optional<mbgl::Duration> {
- if (value.isValid()) {
- return std::chrono::duration_cast<mbgl::Duration>(mbgl::Milliseconds(value.template value<qint64>()));
- };
- return {};
- };
- return mbgl::style::TransitionOptions { convert(options.duration), convert(options.delay) };
-}
-
-auto toQMapboxTransitionOptions(const mbgl::style::TransitionOptions &options) {
- auto convert = [](auto& value) -> QVariant {
- if (value) {
- return qint64(std::chrono::duration_cast<mbgl::Milliseconds>(*value).count());
- }
- return {};
- };
- return QMapbox::TransitionOptions { convert(options.duration), convert(options.delay) };
-}
-
auto fromQStringList(const QStringList &list)
{
std::vector<std::string> strings;
@@ -122,8 +118,9 @@ std::unique_ptr<const mbgl::SpriteImage> toSpriteImage(const QImage &sprite) {
memcpy(img.get(), swapped.constBits(), swapped.byteCount());
return std::make_unique<mbgl::SpriteImage>(
- mbgl::PremultipliedImage{ static_cast<uint16_t>(swapped.width()),
- static_cast<uint16_t>(swapped.height()), std::move(img) },
+ mbgl::PremultipliedImage(
+ { static_cast<uint32_t>(swapped.width()), static_cast<uint32_t>(swapped.height()) },
+ std::move(img)),
1.0);
}
@@ -144,115 +141,235 @@ std::unique_ptr<const mbgl::SpriteImage> toSpriteImage(const QImage &sprite) {
/*!
\enum QMapboxGLSettings::GLContextMode
- This enum set the expectations towards the GL state.
+ This enum sets the expectations for the OpenGL state.
- \value UniqueGLContext The GL context is only used by QMapboxGL, so it is not
+ \value UniqueGLContext The OpenGL context is only used by QMapboxGL, so it is not
reset before each rendering. Use this mode if the intention is to only draw a
fullscreen map.
- \value SharedGLContext The GL context is shared and the state will be restored
- before rendering. This mode is safer when GL calls are performed prior of after
+ \value SharedGLContext The OpenGL context is shared and the state will be restored
+ before rendering. This mode is safer when OpenGL calls are performed prior of after
we call QMapboxGL::render for rendering a map.
\sa contextMode()
*/
/*!
+ \enum QMapboxGLSettings::ConstrainMode
+
+ This enum determines if the map wraps.
+
+ \value NoConstrain The map will wrap on the horizontal axis. Since it doesn't
+ make sense to wrap on the vertical axis in a Web Mercator projection, the map will scroll
+ and show some empty space.
+
+ \value ConstrainHeightOnly The map will wrap around the horizontal axis, like a spinning
+ globe. This is the recommended constrain mode.
+
+ \value ConstrainWidthAndHeight The map won't wrap and panning is restricted to the boundaries
+ of the map.
+
+ \sa constrainMode()
+*/
+
+/*!
+ \enum QMapboxGLSettings::ViewportMode
+
+ This enum flips the map vertically.
+
+ \value DefaultViewport Native orientation.
+
+ \value FlippedYViewport Mirrored vertically.
+
+ \sa viewportMode()
+*/
+
+/*!
Constructs a QMapboxGLSettings object with the default values. The default
configuration is valid for initializing a QMapboxGL.
*/
QMapboxGLSettings::QMapboxGLSettings()
- : m_mapMode(QMapboxGLSettings::ContinuousMap)
- , m_contextMode(QMapboxGLSettings::SharedGLContext)
+ : m_contextMode(QMapboxGLSettings::SharedGLContext)
, m_constrainMode(QMapboxGLSettings::ConstrainHeightOnly)
, m_viewportMode(QMapboxGLSettings::DefaultViewport)
, m_cacheMaximumSize(mbgl::util::DEFAULT_MAX_CACHE_SIZE)
, m_cacheDatabasePath(":memory:")
, m_assetPath(QCoreApplication::applicationDirPath())
, m_accessToken(qgetenv("MAPBOX_ACCESS_TOKEN"))
+ , m_apiBaseUrl(mbgl::util::API_BASE_URL)
{
}
-QMapboxGLSettings::MapMode QMapboxGLSettings::mapMode() const
-{
- return m_mapMode;
-}
-
-void QMapboxGLSettings::setMapMode(MapMode mode)
-{
- m_mapMode = mode;
-}
+/*!
+ Returns the OpenGL context mode. This is specially important when mixing
+ with other OpenGL draw calls.
+ By default, it is set to QMapboxGLSettings::SharedGLContext.
+*/
QMapboxGLSettings::GLContextMode QMapboxGLSettings::contextMode() const
{
return m_contextMode;
}
+/*!
+ Sets the OpenGL context \a mode.
+*/
void QMapboxGLSettings::setContextMode(GLContextMode mode)
{
m_contextMode = mode;
}
+/*!
+ Returns the constrain mode. This is used to limit the map to wrap
+ around the globe horizontally.
+
+ By default, it is set to QMapboxGLSettings::ConstrainHeightOnly.
+*/
QMapboxGLSettings::ConstrainMode QMapboxGLSettings::constrainMode() const
{
return m_constrainMode;
}
+/*!
+ Sets the map constrain \a mode.
+*/
void QMapboxGLSettings::setConstrainMode(ConstrainMode mode)
{
m_constrainMode = mode;
}
+/*!
+ Returns the viewport mode. This is used to flip the vertical
+ orientation of the map as some devices may use inverted orientation.
+
+ By default, it is set to QMapboxGLSettings::DefaultViewport.
+*/
QMapboxGLSettings::ViewportMode QMapboxGLSettings::viewportMode() const
{
return m_viewportMode;
}
+/*!
+ Sets the viewport \a mode.
+*/
void QMapboxGLSettings::setViewportMode(ViewportMode mode)
{
m_viewportMode = mode;
}
+/*!
+ Returns the cache database maximum hard size in bytes. The database
+ will grow until the limit is reached. Setting a maximum size smaller
+ than the current size of an existing database results in undefined
+ behavior
+
+ By default, it is set to 50 MB.
+*/
unsigned QMapboxGLSettings::cacheDatabaseMaximumSize() const
{
return m_cacheMaximumSize;
}
+/*!
+ Returns the maximum allowed cache database \a size in bytes.
+*/
void QMapboxGLSettings::setCacheDatabaseMaximumSize(unsigned size)
{
m_cacheMaximumSize = size;
}
+/*!
+ Returns the cache database path. The cache is used for storing
+ recently used resources like tiles and also an offline tile database
+ pre-populated by the
+ \l {https://github.com/mapbox/mapbox-gl-native/blob/master/bin/offline.sh}
+ {Offline Tool}.
+
+ By default, it is set to \c :memory: meaning it will create an in-memory
+ cache instead of a file on disk.
+*/
QString QMapboxGLSettings::cacheDatabasePath() const
{
return m_cacheDatabasePath;
}
+/*!
+ Sets the cache database \a path.
+
+ Setting the \a path to \c :memory: will create an in-memory cache.
+*/
void QMapboxGLSettings::setCacheDatabasePath(const QString &path)
{
m_cacheDatabasePath = path;
}
+/*!
+ Returns the asset path, which is the root directory from where
+ the \c asset:// scheme gets resolved in a style. \c asset:// can be used
+ for loading a resource from the disk in a style rather than fetching
+ it from the network.
+
+ By default, it is set to the value returned by QCoreApplication::applicationDirPath().
+*/
QString QMapboxGLSettings::assetPath() const
{
return m_assetPath;
}
+/*!
+ Sets the asset \a path.
+*/
void QMapboxGLSettings::setAssetPath(const QString &path)
{
m_assetPath = path;
}
+/*!
+ Returns the access token.
+
+ By default, it is taken from the environment variable \c MAPBOX_ACCESS_TOKEN
+ or empty if the variable is not set.
+*/
QString QMapboxGLSettings::accessToken() const {
return m_accessToken;
}
+/*!
+ Sets the access \a token.
+
+ Mapbox-hosted vector tiles and styles require an API
+ \l {https://www.mapbox.com/help/define-access-token/}{access token}, which you
+ can obtain from the \l {https://www.mapbox.com/studio/account/tokens/}
+ {Mapbox account page}. Access tokens associate requests to Mapbox's vector tile
+ and style APIs with your Mapbox account. They also deter other developers from
+ using your styles without your permission.
+*/
void QMapboxGLSettings::setAccessToken(const QString &token)
{
m_accessToken = token;
}
/*!
+ Returns the API base URL.
+*/
+QString QMapboxGLSettings::apiBaseUrl() const
+{
+ return m_apiBaseUrl;
+}
+
+/*!
+ Sets the API base \a url.
+
+ The API base URL is the URL that the \b "mapbox://" protocol will
+ be resolved to. It defaults to "https://api.mapbox.com" but can be
+ changed, for instance, to a tile cache server address.
+*/
+void QMapboxGLSettings::setApiBaseUrl(const QString& url)
+{
+ m_apiBaseUrl = url;
+}
+
+/*!
\class QMapboxGL
\brief The QMapboxGL class is a Qt wrapper for the Mapbox GL Native engine.
@@ -264,14 +381,84 @@ void QMapboxGLSettings::setAccessToken(const QString &token)
QNetworkAccessManager for HTTP requests and QString for UTF-8 manipulation.
QMapboxGL is not thread-safe and it is assumed that it will be accessed from
- the same thread as the thread where the GL context lives.
+ the same thread as the thread where the OpenGL context lives.
\since 4.7
*/
/*!
+ \enum QMapboxGL::MapChange
+
+ This enum represents the last changed occurred to the map state.
+
+ \value MapChangeRegionWillChange A region of the map will change, like
+ when resizing the map.
+
+ \value MapChangeRegionWillChangeAnimated Not in use by QMapboxGL.
+
+ \value MapChangeRegionIsChanging A region of the map is changing.
+
+ \value MapChangeRegionDidChange A region of the map finished changing.
+
+ \value MapChangeRegionDidChangeAnimated Not in use by QMapboxGL.
+
+ \value MapChangeWillStartLoadingMap The map is getting loaded. This state
+ is set only once right after QMapboxGL is created and a style is set.
+
+ \value MapChangeDidFinishLoadingMap All the resources were loaded and parsed
+ and the map is fully rendered. After this state the mapChanged() signal won't fire again unless
+ the is some client side interaction with the map or a tile expires, causing a new resource
+ to be requested from the network.
+
+ \value MapChangeDidFailLoadingMap An error occurred when loading the map.
+
+ \value MapChangeWillStartRenderingFrame Just before rendering the frame. This
+ is the state of the map just after calling render() and might happened many times before
+ the map is fully loaded.
+
+ \value MapChangeDidFinishRenderingFrame The current frame was rendered but was
+ left in a partial state. Some parts of the map might be missing because have not arrived
+ from the network or are being parsed.
+
+ \value MapChangeDidFinishRenderingFrameFullyRendered The current frame was fully rendered.
+
+ \value MapChangeWillStartRenderingMap Set once when the map is about to get
+ rendered for the first time.
+
+ \value MapChangeDidFinishRenderingMap Not in use by QMapboxGL.
+
+ \value MapChangeDidFinishRenderingMapFullyRendered Map is fully loaded and rendered.
+
+ \value MapChangeDidFinishLoadingStyle The style was loaded.
+
+ \value MapChangeSourceDidChange A source has changed.
+
+ \sa mapChanged()
+*/
+
+/*!
+ \enum QMapboxGL::NorthOrientation
+
+ This enum sets the orientation of the north bearing. It will directly affect bearing when
+ resetting the north (i.e. setting bearing to 0).
+
+ \value NorthUpwards The north is pointing up in the map. This is usually how maps are oriented.
+
+ \value NorthRightwards The north is pointing right.
+
+ \value NorthDownwards The north is pointing down.
+
+ \value NorthLeftwards The north is pointing left.
+
+ \sa northOrientation()
+ \sa bearing()
+*/
+
+/*!
Constructs a QMapboxGL object with \a settings and sets \a parent as the parent
- object. The \a settings cannot be changed after the object is constructed.
+ object. The \a settings cannot be changed after the object is constructed. The
+ \a size represents the size of the viewport and the \a pixelRatio the initial pixel
+ density of the screen.
*/
QMapboxGL::QMapboxGL(QObject *parent, const QMapboxGLSettings &settings, const QSize& size, qreal pixelRatio)
: QObject(parent)
@@ -285,56 +472,76 @@ QMapboxGL::QMapboxGL(QObject *parent, const QMapboxGLSettings &settings, const Q
d_ptr = new QMapboxGLPrivate(this, settings, size, pixelRatio);
}
+/*!
+ Destroys this QMapboxGL.
+*/
QMapboxGL::~QMapboxGL()
{
delete d_ptr;
}
+/*!
+ Cycles through several debug options like showing the tile borders,
+ tile numbers, expiration time and wireframe.
+*/
void QMapboxGL::cycleDebugOptions()
{
d_ptr->mapObj->cycleDebugOptions();
}
-QString QMapboxGL::styleJson() const
-{
- return QString::fromStdString(d_ptr->mapObj->getStyleJSON());
-}
-
-QString QMapboxGL::styleUrl() const
-{
- return QString::fromStdString(d_ptr->mapObj->getStyleURL());
-}
-
/*!
- Sets a new \a style from a JSON that must conform with the
+ \property QMapboxGL::styleJson
+ \brief the map style JSON.
+
+ Sets a new \a style from a JSON that must conform to the
\l {https://www.mapbox.com/mapbox-gl-style-spec/}
- {Mapbox Style Specification}.
+ {Mapbox style specification}.
\note In case of a invalid style it will trigger a mapChanged
- signal with QMapbox::MapChangeDidFailLoadingMap as argument.
+ signal with QMapboxGL::MapChangeDidFailLoadingMap as argument.
*/
+QString QMapboxGL::styleJson() const
+{
+ return QString::fromStdString(d_ptr->mapObj->getStyleJSON());
+}
+
void QMapboxGL::setStyleJson(const QString &style)
{
d_ptr->mapObj->setStyleJSON(style.toStdString());
}
/*!
- Sets a URL for fetching a JSON that will be later feed to
+ \property QMapboxGL::styleUrl
+ \brief the map style URL.
+
+ Sets a URL for fetching a JSON that will be later fed to
setStyleJson. URLs using the Mapbox scheme (\a mapbox://) are
also accepted and translated automatically to an actual HTTPS
request.
- The Mapbox scheme is not enforced by any means and a style can
- be fetched from anything that QNetworkAccessManager can handle.
+ The Mapbox scheme is not enforced and a style can be fetched
+ from anything that QNetworkAccessManager can handle.
\note In case of a invalid style it will trigger a mapChanged
- signal with QMapbox::MapChangeDidFailLoadingMap as argument.
+ signal with QMapboxGL::MapChangeDidFailLoadingMap as argument.
*/
+QString QMapboxGL::styleUrl() const
+{
+ return QString::fromStdString(d_ptr->mapObj->getStyleURL());
+}
+
void QMapboxGL::setStyleUrl(const QString &url)
{
d_ptr->mapObj->setStyleURL(url.toStdString());
}
+/*!
+ \property QMapboxGL::latitude
+ \brief the map's current latitude in degrees.
+
+ Setting a latitude doesn't necessarily mean it will be accepted since QMapboxGL
+ might constrain it within the limits of the Web Mercator projection.
+*/
double QMapboxGL::latitude() const
{
return d_ptr->mapObj->getLatLng(d_ptr->margins).latitude;
@@ -345,6 +552,14 @@ void QMapboxGL::setLatitude(double latitude_)
d_ptr->mapObj->setLatLng(mbgl::LatLng { latitude_, longitude() }, d_ptr->margins);
}
+/*!
+ \property QMapboxGL::longitude
+ \brief the map current longitude in degrees.
+
+ Setting a longitude beyond the limits of the Web Mercator projection will make
+ the map wrap. As an example, setting the longitude to 360 is effectively the same
+ as setting it to 0.
+*/
double QMapboxGL::longitude() const
{
return d_ptr->mapObj->getLatLng(d_ptr->margins).longitude;
@@ -355,6 +570,19 @@ void QMapboxGL::setLongitude(double longitude_)
d_ptr->mapObj->setLatLng(mbgl::LatLng { latitude(), longitude_ }, d_ptr->margins);
}
+/*!
+ \property QMapboxGL::scale
+ \brief the map scale factor.
+
+ This property is used to zoom the map. When \a center is defined, the map will
+ scale in the direction of the center pixel coordinates. The \a center will remain
+ at the same pixel coordinate after scaling as before calling this method.
+
+ \note This function could be used for implementing a pinch gesture or zooming
+ by using the mouse scroll wheel.
+
+ \sa zoom()
+*/
double QMapboxGL::scale() const
{
return d_ptr->mapObj->getScale();
@@ -365,6 +593,16 @@ void QMapboxGL::setScale(double scale_, const QPointF &center)
d_ptr->mapObj->setScale(scale_, mbgl::ScreenCoordinate { center.x(), center.y() });
}
+/*!
+ \property QMapboxGL::zoom
+ \brief the map zoom factor.
+
+ This property is used to zoom the map. When \a center is defined, the map will
+ zoom in the direction of the center. This function could be used for implementing
+ a pinch gesture or zooming by using the mouse scroll wheel.
+
+ \sa scale()
+*/
double QMapboxGL::zoom() const
{
return d_ptr->mapObj->getZoom();
@@ -375,34 +613,66 @@ void QMapboxGL::setZoom(double zoom_)
d_ptr->mapObj->setZoom(zoom_, d_ptr->margins);
}
+/*!
+ Returns the minimum zoom level allowed for the map.
+
+ \sa maximumZoom()
+*/
double QMapboxGL::minimumZoom() const
{
return d_ptr->mapObj->getMinZoom();
}
+/*!
+ Returns the maximum zoom level allowed for the map.
+
+ \sa minimumZoom()
+*/
double QMapboxGL::maximumZoom() const
{
return d_ptr->mapObj->getMaxZoom();
}
+/*!
+ \property QMapboxGL::coordinate
+ \brief the map center \a coordinate.
+
+ Centers the map at a geographic coordinate respecting the margins, if set.
+
+ \sa margins()
+*/
Coordinate QMapboxGL::coordinate() const
{
const mbgl::LatLng& latLng = d_ptr->mapObj->getLatLng(d_ptr->margins);
return Coordinate(latLng.latitude, latLng.longitude);
}
-void QMapboxGL::setCoordinate(const Coordinate &coordinate_)
+void QMapboxGL::setCoordinate(const QMapbox::Coordinate &coordinate_)
{
d_ptr->mapObj->setLatLng(mbgl::LatLng { coordinate_.first, coordinate_.second }, d_ptr->margins);
}
-void QMapboxGL::setCoordinateZoom(const Coordinate &coordinate_, double zoom_)
+/*!
+ \fn QMapboxGL::setCoordinateZoom(const QMapbox::Coordinate &coordinate, double zoom)
+
+ Convenience method for setting the \a coordinate and \a zoom simultaneously.
+
+ \note Setting \a coordinate and \a zoom at once is more efficient than doing
+ it in two steps.
+
+ \sa zoom()
+ \sa coordinate()
+*/
+void QMapboxGL::setCoordinateZoom(const QMapbox::Coordinate &coordinate_, double zoom_)
{
d_ptr->mapObj->setLatLngZoom(
mbgl::LatLng { coordinate_.first, coordinate_.second }, zoom_, d_ptr->margins);
}
-void QMapboxGL::jumpTo(const CameraOptions& camera)
+/*!
+ Atomically jumps to the \a camera options.
+*/
+void QMapboxGL::jumpTo(const QMapboxGLCameraOptions& camera)
{
mbgl::CameraOptions mbglCamera;
if (camera.center.isValid()) {
@@ -428,6 +698,18 @@ void QMapboxGL::jumpTo(const CameraOptions& camera)
d_ptr->mapObj->jumpTo(mbglCamera);
}
+/*!
+ \property QMapboxGL::bearing
+ \brief the map bearing in degrees.
+
+ Set the angle in degrees. Negative values and values over 360 are
+ valid and will wrap. The direction of the rotation is counterclockwise.
+
+ When \a center is defined, the map will rotate around the center pixel coordinate
+ respecting the margins if defined.
+
+ \sa margins()
+*/
double QMapboxGL::bearing() const
{
return d_ptr->mapObj->getBearing();
@@ -443,6 +725,15 @@ void QMapboxGL::setBearing(double degrees, const QPointF &center)
d_ptr->mapObj->setBearing(degrees, mbgl::ScreenCoordinate { center.x(), center.y() });
}
+/*!
+ \property QMapboxGL::pitch
+ \brief the map pitch in degrees.
+
+ Pitch toward the horizon measured in degrees, with 0 resulting in a
+ two-dimensional map. It will be constrained at 60 degrees.
+
+ \sa margins()
+*/
double QMapboxGL::pitch() const
{
return d_ptr->mapObj->getPitch();
@@ -453,41 +744,86 @@ void QMapboxGL::setPitch(double pitch_)
d_ptr->mapObj->setPitch(pitch_);
}
+/*!
+ Returns the north orientation mode.
+*/
QMapboxGL::NorthOrientation QMapboxGL::northOrientation() const
{
return static_cast<QMapboxGL::NorthOrientation>(d_ptr->mapObj->getNorthOrientation());
}
+/*!
+ Sets the north orientation mode to \a orientation.
+*/
void QMapboxGL::setNorthOrientation(NorthOrientation orientation)
{
d_ptr->mapObj->setNorthOrientation(static_cast<mbgl::NorthOrientation>(orientation));
}
-void QMapboxGL::setGestureInProgress(bool inProgress)
+/*!
+ Tells the map rendering engine that there is currently a gesture in \a progress. This
+ affects how the map renders labels, as it will use different texture filters if a gesture
+ is ongoing.
+*/
+void QMapboxGL::setGestureInProgress(bool progress)
{
- d_ptr->mapObj->setGestureInProgress(inProgress);
+ d_ptr->mapObj->setGestureInProgress(progress);
}
+/*!
+ Adds an \a className to the list of active classes. Layers tagged with a certain class
+ will only be active when the class is added.
+
+ This was removed from the \l {https://www.mapbox.com/mapbox-gl-style-spec/#layer-paint.*}
+ {Mapbox style specification} and should no longer be used.
+
+ \deprecated
+ \sa removeClass()
+*/
void QMapboxGL::addClass(const QString &className)
{
d_ptr->mapObj->addClass(className.toStdString());
}
+/*!
+ Removes a \a className.
+
+ \deprecated
+ \sa addClass()
+*/
void QMapboxGL::removeClass(const QString &className)
{
d_ptr->mapObj->removeClass(className.toStdString());
}
+/*!
+ Returns true when \a className is active, false otherwise.
+
+ \deprecated
+ \sa addClass()
+*/
bool QMapboxGL::hasClass(const QString &className) const
{
return d_ptr->mapObj->hasClass(className.toStdString());
}
+/*!
+ Bulk adds a list of \a classNames.
+
+ \deprecated
+ \sa addClass()
+*/
void QMapboxGL::setClasses(const QStringList &classNames)
{
d_ptr->mapObj->setClasses(fromQStringList(classNames));
}
+/*!
+ Returns a list of active classes.
+
+ \deprecated
+ \sa setClasses()
+*/
QStringList QMapboxGL::getClasses() const
{
QStringList classNames;
@@ -497,12 +833,19 @@ QStringList QMapboxGL::getClasses() const
return classNames;
}
-QMapbox::TransitionOptions QMapboxGL::getTransitionOptions() const {
- return toQMapboxTransitionOptions(d_ptr->mapObj->getTransitionOptions());
-}
+/*!
+ Sets the \a duration and \a delay of style class transitions. Style property
+ values transition to new values with animation when a new class is set.
+
+ \deprecated
+ \sa addClass()
+*/
+void QMapboxGL::setTransitionOptions(qint64 duration, qint64 delay) {
+ static auto convert = [](qint64 value) -> mbgl::optional<mbgl::Duration> {
+ return std::chrono::duration_cast<mbgl::Duration>(mbgl::Milliseconds(value));
+ };
-void QMapboxGL::setTransitionOptions(const QMapbox::TransitionOptions &options) {
- d_ptr->mapObj->setTransitionOptions(fromQMapboxTransitionOptions(options));
+ d_ptr->mapObj->setTransitionOptions(mbgl::style::TransitionOptions{ convert(duration), convert(delay) });
}
mbgl::Annotation fromPointAnnotation(const PointAnnotation &pointAnnotation) {
@@ -511,92 +854,206 @@ mbgl::Annotation fromPointAnnotation(const PointAnnotation &pointAnnotation) {
return mbgl::SymbolAnnotation { mbgl::Point<double> { coordinate.second, coordinate.first }, icon.toStdString() };
}
-AnnotationID QMapboxGL::addPointAnnotation(const PointAnnotation &pointAnnotation)
+/*!
+ Adds a \a point annotation to the map.
+
+ Returns the unique identifier for the new annotation.
+
+ \sa addAnnotationIcon()
+*/
+QMapbox::AnnotationID QMapboxGL::addPointAnnotation(const QMapbox::PointAnnotation &point)
{
- return d_ptr->mapObj->addAnnotation(fromPointAnnotation(pointAnnotation));
+ return d_ptr->mapObj->addAnnotation(fromPointAnnotation(point));
}
-void QMapboxGL::updatePointAnnotation(AnnotationID id, const PointAnnotation &pointAnnotation)
+/*!
+ Updates an existing \a point annotation referred by \a id.
+
+ \sa addAnnotationIcon()
+*/
+void QMapboxGL::updatePointAnnotation(QMapbox::AnnotationID id, const QMapbox::PointAnnotation &point)
{
- d_ptr->mapObj->updateAnnotation(id, fromPointAnnotation(pointAnnotation));
+ d_ptr->mapObj->updateAnnotation(id, fromPointAnnotation(point));
}
-AnnotationID QMapboxGL::addShapeAnnotation(const ShapeAnnotation &shapeAnnotation)
+/*!
+ Adds a \a shape annotation to the map.
+
+ Returns the unique identifier for the new annotation.
+*/
+QMapbox::AnnotationID QMapboxGL::addShapeAnnotation(const QMapbox::ShapeAnnotation &shape)
{
- return d_ptr->mapObj->addAnnotation(fromQMapboxGLShapeAnnotation(shapeAnnotation));
+ return d_ptr->mapObj->addAnnotation(fromQMapboxGLShapeAnnotation(shape));
}
-void QMapboxGL::removeAnnotation(AnnotationID annotationID)
+/*!
+ Removes an existing annotation referred by \a id.
+*/
+void QMapboxGL::removeAnnotation(QMapbox::AnnotationID id)
{
- d_ptr->mapObj->removeAnnotation(annotationID);
+ d_ptr->mapObj->removeAnnotation(id);
}
-void QMapboxGL::setLayoutProperty(const QString& layer_, const QString& property, const QVariant& value)
+/*!
+ Sets a layout \a property \a value to an existing \a layer. The \a property string can be any
+ as defined by the \l {https://www.mapbox.com/mapbox-gl-style-spec/} {Mapbox style specification}
+ for layout properties.
+
+ This example hides the layer \c route:
+
+ \code
+ map->setLayoutProperty("route", "visibility", "none");
+ \endcode
+
+ This table describes the mapping between \l {https://www.mapbox.com/mapbox-gl-style-spec/#types}
+ {style types} and Qt types accepted by setLayoutProperty():
+
+ \table
+ \header
+ \li Mapbox style type
+ \li Qt type
+ \row
+ \li Enum
+ \li QString
+ \row
+ \li String
+ \li QString
+ \row
+ \li Boolean
+ \li \c bool
+ \row
+ \li Number
+ \li \c int, \c double or \c float
+ \row
+ \li Array
+ \li QVariantList
+ \endtable
+*/
+void QMapboxGL::setLayoutProperty(const QString& layer, const QString& property, const QVariant& value)
{
using namespace mbgl::style;
- Layer* layer = d_ptr->mapObj->getLayer(layer_.toStdString());
- if (!layer) {
- qWarning() << "Layer not found:" << layer_;
+ Layer* layer_ = d_ptr->mapObj->getLayer(layer.toStdString());
+ if (!layer_) {
+ qWarning() << "Layer not found:" << layer;
return;
}
- if (conversion::setLayoutProperty(*layer, property.toStdString(), value)) {
- qWarning() << "Error setting layout property:" << layer_ << "-" << property;
+ if (conversion::setLayoutProperty(*layer_, property.toStdString(), value)) {
+ qWarning() << "Error setting layout property:" << layer << "-" << property;
return;
}
}
-void QMapboxGL::setPaintProperty(const QString& layer_, const QString& property, const QVariant& value, const QString& klass_)
+/*!
+ Sets a paint \a property \a value to an existing \a layer. The \a property string can be any
+ as defined by the \l {https://www.mapbox.com/mapbox-gl-style-spec/} {Mapbox style specification}
+ for paint properties.
+
+ The argument \a styleClass is deprecated and is used for defining the style class for the paint
+ property.
+
+ For paint properties that take a color as \a value, such as \c fill-color, a string such as
+ \c blue can be passed or a QColor.
+
+ \code
+ map->setPaintProperty("route", "line-color", QColor("blue"));
+ \endcode
+
+ This table describes the mapping between \l {https://www.mapbox.com/mapbox-gl-style-spec/#types}
+ {style types} and Qt types accepted by setPaintProperty():
+
+ \table
+ \header
+ \li Mapbox style type
+ \li Qt type
+ \row
+ \li Color
+ \li QString or QColor
+ \row
+ \li Enum
+ \li QString
+ \row
+ \li String
+ \li QString
+ \row
+ \li Boolean
+ \li \c bool
+ \row
+ \li Number
+ \li \c int, \c double or \c float
+ \row
+ \li Array
+ \li QVariantList
+ \endtable
+
+ If the style specification defines the property's type as \b Array, use a QVariantList. For
+ example, the following code sets a \c route layer's \c line-dasharray property:
+
+ \code
+ QVariantList lineDashArray;
+ lineDashArray.append(1);
+ lineDashArray.append(2);
+
+ map->setPaintProperty("route","line-dasharray", lineDashArray);
+ \endcode
+*/
+void QMapboxGL::setPaintProperty(const QString& layer, const QString& property, const QVariant& value, const QString& styleClass)
{
using namespace mbgl::style;
- Layer* layer = d_ptr->mapObj->getLayer(layer_.toStdString());
- if (!layer) {
- qWarning() << "Layer not found:" << layer_;
+ Layer* layer_ = d_ptr->mapObj->getLayer(layer.toStdString());
+ if (!layer_) {
+ qWarning() << "Layer not found:" << layer;
return;
}
mbgl::optional<std::string> klass;
- if (!klass_.isEmpty()) {
- klass = klass_.toStdString();
+ if (!styleClass.isEmpty()) {
+ klass = styleClass.toStdString();
}
- if (conversion::setPaintProperty(*layer, property.toStdString(), value, klass)) {
- qWarning() << "Error setting paint property:" << layer_ << "-" << property;
+ if (conversion::setPaintProperty(*layer_, property.toStdString(), value, klass)) {
+ qWarning() << "Error setting paint property:" << layer << "-" << property;
return;
}
}
-bool QMapboxGL::isRotating() const
-{
- return d_ptr->mapObj->isRotating();
-}
-
-bool QMapboxGL::isScaling() const
-{
- return d_ptr->mapObj->isScaling();
-}
-
-bool QMapboxGL::isPanning() const
-{
- return d_ptr->mapObj->isPanning();
-}
-
+/*!
+ Returns true when the map is completely rendered, false otherwise. A partially
+ rendered map ranges from nothing rendered at all to only labels missing.
+*/
bool QMapboxGL::isFullyLoaded() const
{
return d_ptr->mapObj->isFullyLoaded();
}
+/*!
+ Pan the map by \a offset in pixels.
+
+ The pixel coordinate origin is located at the upper left corner of the map.
+*/
void QMapboxGL::moveBy(const QPointF &offset)
{
d_ptr->mapObj->moveBy(mbgl::ScreenCoordinate { offset.x(), offset.y() });
}
+/*!
+ \fn QMapboxGL::scaleBy(double scale, const QPointF &center)
+
+ Scale the map by \a scale in the direction of the \a center. This function
+ can be used for implementing a pinch gesture.
+*/
void QMapboxGL::scaleBy(double scale_, const QPointF &center) {
d_ptr->mapObj->scaleBy(scale_, mbgl::ScreenCoordinate { center.x(), center.y() });
}
+/*!
+ Rotate the map from the \a first screen coordinate to the \a second screen coordinate.
+ This method can be used for implementing rotating the map by clicking and dragging,
+ being \a first the cursor coordinate at the last frame and \a second the cursor coordinate
+ at the current frame.
+*/
void QMapboxGL::rotateBy(const QPointF &first, const QPointF &second)
{
d_ptr->mapObj->rotateBy(
@@ -604,6 +1061,17 @@ void QMapboxGL::rotateBy(const QPointF &first, const QPointF &second)
mbgl::ScreenCoordinate { second.x(), second.y() });
}
+/*!
+ Resize the map to \a size and scale to fit at \a framebufferSize. For
+ high DPI screens, the size will be smaller than the \a framebufferSize.
+
+ This fallowing example will double the pixel density of the map for
+ a given \c size:
+
+ \code
+ map->resize(size / 2, size);
+ \endcode
+*/
void QMapboxGL::resize(const QSize& size, const QSize& framebufferSize)
{
if (d_ptr->size == size && d_ptr->fbSize == framebufferSize) return;
@@ -611,17 +1079,38 @@ void QMapboxGL::resize(const QSize& size, const QSize& framebufferSize)
d_ptr->size = size;
d_ptr->fbSize = framebufferSize;
- d_ptr->mapObj->setSize({{ static_cast<uint16_t>(size.width()), static_cast<uint16_t>(size.height()) }});
+ d_ptr->mapObj->setSize(
+ { static_cast<uint32_t>(size.width()), static_cast<uint32_t>(size.height()) });
}
-void QMapboxGL::addAnnotationIcon(const QString &name, const QImage &sprite)
+/*!
+ Adds an \a icon to the annotation icon pool. This can be later used by the annotation
+ functions to shown any drawing on the map by referencing its \a name.
+
+ Unlike using addIcon() for runtime styling, annotations added with addPointAnnotation()
+ will survive style changes.
+
+ \sa addPointAnnotation()
+*/
+void QMapboxGL::addAnnotationIcon(const QString &name, const QImage &icon)
{
- if (sprite.isNull()) return;
+ if (icon.isNull()) return;
- d_ptr->mapObj->addAnnotationIcon(name.toStdString(), toSpriteImage(sprite));
+ d_ptr->mapObj->addAnnotationIcon(name.toStdString(), toSpriteImage(icon));
}
-QPointF QMapboxGL::pixelForCoordinate(const Coordinate &coordinate_) const
+/*!
+ \fn QMapboxGL::pixelForCoordinate(const QMapbox::Coordinate &coordinate) const
+
+ Returns the offset in pixels for \a coordinate. The origin pixel coordinate is
+ located at the top left corner of the map view.
+
+ This method returns the correct value for any coordinate, even if the coordinate
+ is not currently visible on the screen.
+
+ /note The return value is affected by the current zoom level, bearing and pitch.
+*/
+QPointF QMapboxGL::pixelForCoordinate(const QMapbox::Coordinate &coordinate_) const
{
const mbgl::ScreenCoordinate pixel =
d_ptr->mapObj->pixelForLatLng(mbgl::LatLng { coordinate_.first, coordinate_.second });
@@ -629,7 +1118,10 @@ QPointF QMapboxGL::pixelForCoordinate(const Coordinate &coordinate_) const
return QPointF(pixel.x, pixel.y);
}
-Coordinate QMapboxGL::coordinateForPixel(const QPointF &pixel) const
+/*!
+ Returns the geographic coordinate for the \a pixel coordinate.
+*/
+QMapbox::Coordinate QMapboxGL::coordinateForPixel(const QPointF &pixel) const
{
const mbgl::LatLng latLng =
d_ptr->mapObj->latLngForPixel(mbgl::ScreenCoordinate { pixel.x(), pixel.y() });
@@ -637,7 +1129,11 @@ Coordinate QMapboxGL::coordinateForPixel(const QPointF &pixel) const
return Coordinate(latLng.latitude, latLng.longitude);
}
-CoordinateZoom QMapboxGL::coordinateZoomForBounds(const Coordinate &sw, Coordinate &ne) const
+/*!
+ Returns the coordinate and zoom combination needed in order to make the coordinate
+ bounding box \a sw and \a ne visible.
+*/
+QMapbox::CoordinateZoom QMapboxGL::coordinateZoomForBounds(const QMapbox::Coordinate &sw, QMapbox::Coordinate &ne) const
{
auto bounds = mbgl::LatLngBounds::hull(mbgl::LatLng { sw.first, sw.second }, mbgl::LatLng { ne.first, ne.second });
mbgl::CameraOptions camera = d_ptr->mapObj->cameraForLatLngBounds(bounds, d_ptr->margins);
@@ -645,8 +1141,13 @@ CoordinateZoom QMapboxGL::coordinateZoomForBounds(const Coordinate &sw, Coordina
return {{ (*camera.center).latitude, (*camera.center).longitude }, *camera.zoom };
}
-CoordinateZoom QMapboxGL::coordinateZoomForBounds(const Coordinate &sw, Coordinate &ne,
+/*!
+ Returns the coordinate and zoom combination needed in order to make the coordinate
+ bounding box \a sw and \a ne visible taking into account \a newBearing and \a newPitch.
+*/
+QMapbox::CoordinateZoom QMapboxGL::coordinateZoomForBounds(const QMapbox::Coordinate &sw, QMapbox::Coordinate &ne,
double newBearing, double newPitch)
+
{
// FIXME: mbgl::Map::cameraForLatLngBounds should
// take bearing and pitch as input too, so this
@@ -666,6 +1167,12 @@ CoordinateZoom QMapboxGL::coordinateZoomForBounds(const Coordinate &sw, Coordina
return {{ (*camera.center).latitude, (*camera.center).longitude }, *camera.zoom };
}
+/*!
+ \property QMapboxGL::margins
+ \brief the map margins in pixels from the corners of the map.
+
+ This property sets a new reference center for the map.
+*/
void QMapboxGL::setMargins(const QMargins &margins_)
{
d_ptr->margins = {
@@ -686,12 +1193,30 @@ QMargins QMapboxGL::margins() const
);
}
-void QMapboxGL::addSource(const QString &sourceID, const QVariantMap &params)
+/*!
+ Adds a source \a id to the map as specified by the \l
+ {https://www.mapbox.com/mapbox-gl-style-spec/#root-sources}{Mapbox style specification} with
+ \a params.
+
+ This example reads a GeoJSON from the Qt resource system and adds it as source:
+
+ \code
+ QFile geojson(":source1.geojson");
+ geojson.open(QIODevice::ReadOnly);
+
+ QVariantMap routeSource;
+ routeSource["type"] = "geojson";
+ routeSource["data"] = geojson.readAll();
+
+ map->addSource("routeSource", routeSource);
+ \endcode
+*/
+void QMapboxGL::addSource(const QString &id, const QVariantMap &params)
{
using namespace mbgl::style;
using namespace mbgl::style::conversion;
- Result<std::unique_ptr<Source>> source = convert<std::unique_ptr<Source>>(QVariant(params), sourceID.toStdString());
+ Result<std::unique_ptr<Source>> source = convert<std::unique_ptr<Source>>(QVariant(params), id.toStdString());
if (!source) {
qWarning() << "Unable to add source:" << source.error().message.c_str();
return;
@@ -700,16 +1225,64 @@ void QMapboxGL::addSource(const QString &sourceID, const QVariantMap &params)
d_ptr->mapObj->addSource(std::move(*source));
}
-void QMapboxGL::removeSource(const QString& sourceID)
+/*!
+ Updates the source \a id with new \a params.
+
+ If the source does not exist, it will be added like in addSource(). Only
+ GeoJSON sources can be updated.
+*/
+void QMapboxGL::updateSource(const QString &id, const QVariantMap &params)
+{
+ using namespace mbgl::style;
+ using namespace mbgl::style::conversion;
+
+ auto source = d_ptr->mapObj->getSource(id.toStdString());
+ if (!source) {
+ addSource(id, params);
+ return;
+ }
+
+ auto sourceGeoJSON = source->as<GeoJSONSource>();
+ if (!sourceGeoJSON) {
+ qWarning() << "Unable to update source: only GeoJSON sources are mutable.";
+ return;
+ }
+
+ if (params.contains("data")) {
+ auto result = convertGeoJSON(params["data"]);
+ if (result) {
+ sourceGeoJSON->setGeoJSON(*result);
+ }
+ }
+}
+
+/*!
+ Removes the source \a id.
+
+ This method has no effect if the source does not exist.
+*/
+void QMapboxGL::removeSource(const QString& id)
{
- d_ptr->mapObj->removeSource(sourceID.toStdString());
+ auto sourceIDStdString = id.toStdString();
+
+ if (d_ptr->mapObj->getSource(sourceIDStdString)) {
+ d_ptr->mapObj->removeSource(sourceIDStdString);
+ }
}
+/*!
+ Adds a custom layer \a id with the initialization function \a initFn, the
+ render function \a renderFn and the deinitialization function \a deinitFn with
+ the user data \a context before the existing layer \a before.
+
+ \warning This is used for delegating the rendering of a layer to the user of
+ this API and is not officially supported. Use at your own risk.
+*/
void QMapboxGL::addCustomLayer(const QString &id,
QMapbox::CustomLayerInitializeFunction initFn,
QMapbox::CustomLayerRenderFunction renderFn,
QMapbox::CustomLayerDeinitializeFunction deinitFn,
- void *context_,
+ void *context,
char *before)
{
d_ptr->mapObj->addLayer(std::make_unique<mbgl::style::CustomLayer>(
@@ -719,10 +1292,29 @@ void QMapboxGL::addCustomLayer(const QString &id,
// CustomLayerRenderParameters members remains the same.
(mbgl::style::CustomLayerRenderFunction)renderFn,
reinterpret_cast<mbgl::style::CustomLayerDeinitializeFunction>(deinitFn),
- context_),
+ context),
before ? mbgl::optional<std::string>(before) : mbgl::optional<std::string>());
}
+/*!
+ Adds a style layer to the map as specified by the \l
+ {https://www.mapbox.com/mapbox-gl-style-spec/#root-layers}{Mapbox style specification} with
+ \a params.
+
+ This example shows how to add a layer that will be used to show a route line on the map. Note
+ that nothing will be drawn until we set paint properties using setPaintProperty().
+
+ \code
+ QVariantMap route;
+ route["id"] = "route";
+ route["type"] = "line";
+ route["source"] = "routeSource";
+
+ map->addLayer(route);
+ \endcode
+
+ /note The source must exist prior to adding a layer.
+*/
void QMapboxGL::addLayer(const QVariantMap &params)
{
using namespace mbgl::style;
@@ -737,83 +1329,167 @@ void QMapboxGL::addLayer(const QVariantMap &params)
d_ptr->mapObj->addLayer(std::move(*layer));
}
+/*!
+ Removes the layer \a id.
+*/
void QMapboxGL::removeLayer(const QString& id)
{
d_ptr->mapObj->removeLayer(id.toStdString());
}
-void QMapboxGL::addImage(const QString &name, const QImage &sprite)
+/*!
+ Adds the \a image with the identifier \a id that can be used
+ later by a symbol layer.
+
+ If the \a id was already added, it gets replaced by the new
+ \a image only if the dimensions of the image are the same as
+ the old image, otherwise it has no effect.
+
+ \sa addLayer()
+*/
+void QMapboxGL::addImage(const QString &id, const QImage &image)
{
- if (sprite.isNull()) return;
+ if (image.isNull()) return;
- d_ptr->mapObj->addImage(name.toStdString(), toSpriteImage(sprite));
+ d_ptr->mapObj->addImage(id.toStdString(), toSpriteImage(image));
}
-void QMapboxGL::removeImage(const QString &name)
+/*!
+ Removes the image \a id.
+*/
+void QMapboxGL::removeImage(const QString &id)
{
- d_ptr->mapObj->removeImage(name.toStdString());
+ d_ptr->mapObj->removeImage(id.toStdString());
}
-void QMapboxGL::setFilter(const QString& layer_, const QVariant& filter_)
+/*!
+ Adds a \a filter to a style \a layer using the format described in the \l
+ {https://www.mapbox.com/mapbox-gl-style-spec/#types-filter}{Mapbox style specification}.
+
+ Given a layer \c marker from an arbitrary GeoJSON source containing features of type \b
+ "Point" and \b "LineString", this example shows how to make sure the layer will only tag
+ features of type \b "Point".
+
+ \code
+ QVariantList filterExpression;
+ filterExpression.append("==");
+ filterExpression.append("$type");
+ filterExpression.append("Point");
+
+ QVariantList filter;
+ filter.append(filterExpression);
+
+ map->setFilter("marker", filter);
+ \endcode
+*/
+void QMapboxGL::setFilter(const QString& layer, const QVariant& filter)
{
using namespace mbgl::style;
using namespace mbgl::style::conversion;
- Layer* layer = d_ptr->mapObj->getLayer(layer_.toStdString());
- if (!layer) {
- qWarning() << "Layer not found:" << layer_;
+ Layer* layer_ = d_ptr->mapObj->getLayer(layer.toStdString());
+ if (!layer_) {
+ qWarning() << "Layer not found:" << layer;
return;
}
- Filter filter;
+ Filter filter_;
- Result<Filter> converted = convert<Filter>(filter_);
+ Result<Filter> converted = convert<Filter>(filter);
if (!converted) {
qWarning() << "Error parsing filter:" << converted.error().message.c_str();
return;
}
- filter = std::move(*converted);
+ filter_ = std::move(*converted);
- if (layer->is<FillLayer>()) {
- layer->as<FillLayer>()->setFilter(filter);
+ if (layer_->is<FillLayer>()) {
+ layer_->as<FillLayer>()->setFilter(filter_);
return;
}
- if (layer->is<LineLayer>()) {
- layer->as<LineLayer>()->setFilter(filter);
+ if (layer_->is<LineLayer>()) {
+ layer_->as<LineLayer>()->setFilter(filter_);
return;
}
- if (layer->is<SymbolLayer>()) {
- layer->as<SymbolLayer>()->setFilter(filter);
+ if (layer_->is<SymbolLayer>()) {
+ layer_->as<SymbolLayer>()->setFilter(filter_);
return;
}
- if (layer->is<CircleLayer>()) {
- layer->as<CircleLayer>()->setFilter(filter);
+ if (layer_->is<CircleLayer>()) {
+ layer_->as<CircleLayer>()->setFilter(filter_);
return;
}
qWarning() << "Layer doesn't support filters";
}
+/*!
+ Renders the map using OpenGL draw calls. If \a fbo is passed, it will
+ make sure to bind the framebuffer object before drawing; otherwise a
+ valid OpenGL context is expected with an appropriate OpenGL viewport state set
+ for the size of the canvas.
+
+ This function should be called only after the signal needsRendering() is
+ emitted at least once.
+*/
#if QT_VERSION >= 0x050000
void QMapboxGL::render(QOpenGLFramebufferObject *fbo)
{
d_ptr->dirty = false;
- d_ptr->updateFramebufferBinding(fbo);
+ d_ptr->fbo = fbo;
d_ptr->mapObj->render(*d_ptr);
}
#else
void QMapboxGL::render()
{
+#if defined(__APPLE__)
+ // FIXME Qt 4.x provides an incomplete FBO at start.
+ // See https://bugreports.qt.io/browse/QTBUG-36802 for details.
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+ return;
+ }
+#endif
+
d_ptr->dirty = false;
d_ptr->mapObj->render(*d_ptr);
}
#endif
+/*!
+ Informs the map that the network connection has been established, causing
+ all network requests that previously timed out to be retried immediately.
+*/
void QMapboxGL::connectionEstablished()
{
d_ptr->connectionEstablished();
}
+/*!
+ \fn void QMapboxGL::needsRendering()
+
+ This signal is emitted when the visual contents of the map have changed
+ and a redraw is needed in order to keep the map visually consistent
+ with the current state.
+
+ \sa render()
+*/
+
+/*!
+ \fn void QMapboxGL::mapChanged(QMapboxGL::MapChange change)
+
+ This signal is emitted when the state of the map has changed. This signal
+ may be used for detecting errors when loading a style or detecting when
+ a map is fully loaded by analyzing the parameter \a change.
+*/
+
+/*!
+ \fn void QMapboxGL::copyrightsChanged(const QString &copyrightsHtml);
+
+ This signal is emitted when the copyrights of the current content of the map
+ have changed. This can be caused by a style change or adding a new source.
+
+ \a copyrightsHtml is a string with a HTML snippet.
+*/
+
QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settings, const QSize &size_, qreal pixelRatio)
: QObject(q)
, size(size_)
@@ -824,18 +1500,21 @@ QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settin
settings.cacheDatabaseMaximumSize()))
, threadPool(4)
, mapObj(std::make_unique<mbgl::Map>(
- *this, std::array<uint16_t, 2>{{ static_cast<uint16_t>(size.width()), static_cast<uint16_t>(size.height()) }},
+ *this, mbgl::Size{ static_cast<uint32_t>(size.width()), static_cast<uint32_t>(size.height()) },
pixelRatio, *fileSourceObj, threadPool,
- static_cast<mbgl::MapMode>(settings.mapMode()),
+ mbgl::MapMode::Continuous,
static_cast<mbgl::GLContextMode>(settings.contextMode()),
static_cast<mbgl::ConstrainMode>(settings.constrainMode()),
static_cast<mbgl::ViewportMode>(settings.viewportMode())))
{
- qRegisterMetaType<QMapbox::MapChange>("QMapbox::MapChange");
+ qRegisterMetaType<QMapboxGL::MapChange>("QMapboxGL::MapChange");
fileSourceObj->setAccessToken(settings.accessToken().toStdString());
+ fileSourceObj->setAPIBaseURL(settings.apiBaseUrl().toStdString());
+
connect(this, SIGNAL(needsRendering()), q_ptr, SIGNAL(needsRendering()), Qt::QueuedConnection);
- connect(this, SIGNAL(mapChanged(QMapbox::MapChange)), q_ptr, SIGNAL(mapChanged(QMapbox::MapChange)), Qt::QueuedConnection);
+ connect(this, SIGNAL(mapChanged(QMapboxGL::MapChange)), q_ptr, SIGNAL(mapChanged(QMapboxGL::MapChange)), Qt::QueuedConnection);
+ connect(this, SIGNAL(copyrightsChanged(QString)), q_ptr, SIGNAL(copyrightsChanged(QString)), Qt::QueuedConnection);
}
QMapboxGLPrivate::~QMapboxGLPrivate()
@@ -843,39 +1522,21 @@ QMapboxGLPrivate::~QMapboxGLPrivate()
}
#if QT_VERSION >= 0x050000
-void QMapboxGLPrivate::updateFramebufferBinding(QOpenGLFramebufferObject *fbo_)
-{
- fbo = fbo_;
- if (fbo) {
- getContext().bindFramebuffer.setDirty();
- getContext().viewport.setCurrentValue(
- { 0, 0, static_cast<uint16_t>(fbo->width()), static_cast<uint16_t>(fbo->height()) });
- } else {
- getContext().bindFramebuffer.setCurrentValue(0);
- getContext().viewport.setCurrentValue({ 0, 0, static_cast<uint16_t>(fbSize.width()),
- static_cast<uint16_t>(fbSize.height()) });
- }
-}
-
-void QMapboxGLPrivate::bind()
-{
+void QMapboxGLPrivate::bind() {
if (fbo) {
fbo->bind();
getContext().bindFramebuffer.setDirty();
- getContext().viewport = { 0, 0, static_cast<uint16_t>(fbo->width()),
- static_cast<uint16_t>(fbo->height()) };
- } else {
- getContext().bindFramebuffer = 0;
- getContext().viewport = { 0, 0, static_cast<uint16_t>(fbSize.width()),
- static_cast<uint16_t>(fbSize.height()) };
+ getContext().viewport = {
+ 0, 0, { static_cast<uint32_t>(fbo->width()), static_cast<uint32_t>(fbo->height()) }
+ };
}
}
#else
-void QMapboxGLPrivate::bind()
-{
+void QMapboxGLPrivate::bind() {
getContext().bindFramebuffer = 0;
- getContext().viewport = { 0, 0, static_cast<uint16_t>(fbSize.width()),
- static_cast<uint16_t>(fbSize.height()) };
+ getContext().viewport = {
+ 0, 0, { static_cast<uint32_t>(fbSize.width()), static_cast<uint32_t>(fbSize.height()) }
+ };
}
#endif
@@ -889,7 +1550,17 @@ void QMapboxGLPrivate::invalidate()
void QMapboxGLPrivate::notifyMapChange(mbgl::MapChange change)
{
- emit mapChanged(static_cast<QMapbox::MapChange>(change));
+ if (change == mbgl::MapChangeSourceDidChange) {
+ std::string attribution;
+ for (const auto& source : mapObj->getSources()) {
+ // Avoid duplicates by using the most complete attribution HTML snippet.
+ if (source->getAttribution() && (attribution.size() < source->getAttribution()->size()))
+ attribution = *source->getAttribution();
+ }
+ emit copyrightsChanged(QString::fromStdString(attribution));
+ }
+
+ emit mapChanged(static_cast<QMapboxGL::MapChange>(change));
}
void QMapboxGLPrivate::connectionEstablished()
diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp
index e7a14601c1..3d2be90273 100644
--- a/platform/qt/src/qmapboxgl_p.hpp
+++ b/platform/qt/src/qmapboxgl_p.hpp
@@ -5,7 +5,7 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/backend.hpp>
#include <mbgl/map/view.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/util/geo.hpp>
@@ -31,10 +31,6 @@ public:
void invalidate() final;
void notifyMapChange(mbgl::MapChange) final;
-#if QT_VERSION >= 0x050000
- void updateFramebufferBinding(QOpenGLFramebufferObject *);
-#endif
-
mbgl::EdgeInsets margins;
QSize size { 0, 0 };
QSize fbSize { 0, 0 };
@@ -54,5 +50,6 @@ public slots:
signals:
void needsRendering();
- void mapChanged(QMapbox::MapChange);
+ void mapChanged(QMapboxGL::MapChange);
+ void copyrightsChanged(const QString &copyrightsHtml);
};
diff --git a/platform/qt/src/qquickmapboxgl.cpp b/platform/qt/src/qquickmapboxgl.cpp
index b17d8bfe3e..7325bfe3c2 100644
--- a/platform/qt/src/qquickmapboxgl.cpp
+++ b/platform/qt/src/qquickmapboxgl.cpp
@@ -1,6 +1,5 @@
#include "qquickmapboxgl.hpp"
-#include "qmapbox.hpp"
#include "qquickmapboxglmapparameter.hpp"
#include "qquickmapboxglrenderer.hpp"
@@ -202,9 +201,9 @@ void QQuickMapboxGL::pan(int dx, int dy)
update();
}
-void QQuickMapboxGL::onMapChanged(QMapbox::MapChange change)
+void QQuickMapboxGL::onMapChanged(QMapboxGL::MapChange change)
{
- if (change == QMapbox::MapChangeDidFinishLoadingStyle) {
+ if (change == QMapboxGL::MapChangeDidFinishLoadingStyle) {
m_styleLoaded = true;
update();
}
@@ -290,9 +289,14 @@ bool QQuickMapboxGL::parseStyleSource(QQuickMapboxGLMapParameter *param)
source["url"] = param->property("url");
m_sourceChanges << source;
} else if (sourceType == "geojson") {
- QFile geojson(param->property("data").toString());
- geojson.open(QIODevice::ReadOnly);
- source["data"] = geojson.readAll();
+ auto data = param->property("data").toString();
+ if (data.startsWith(':')) {
+ QFile geojson(data);
+ geojson.open(QIODevice::ReadOnly);
+ source["data"] = geojson.readAll();
+ } else {
+ source["data"] = data.toUtf8();
+ }
m_sourceChanges << source;
} else {
m_error = QGeoServiceProvider::UnknownParameterError;
diff --git a/platform/qt/src/qquickmapboxgl.hpp b/platform/qt/src/qquickmapboxgl.hpp
index 64cc41bf78..a6561d4bb4 100644
--- a/platform/qt/src/qquickmapboxgl.hpp
+++ b/platform/qt/src/qquickmapboxgl.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "qmapbox.hpp"
+#include "qmapboxgl.hpp"
#include "qquickmapboxglmapparameter.hpp"
#include <QColor>
@@ -98,7 +99,7 @@ public slots:
void setCenter(const QGeoCoordinate &center);
private slots:
- void onMapChanged(QMapbox::MapChange);
+ void onMapChanged(QMapboxGL::MapChange);
void onParameterPropertyUpdated(const QString &name);
private:
diff --git a/platform/qt/src/qquickmapboxglrenderer.cpp b/platform/qt/src/qquickmapboxglrenderer.cpp
index 903e1c0b05..69c22d35d7 100644
--- a/platform/qt/src/qquickmapboxglrenderer.cpp
+++ b/platform/qt/src/qquickmapboxglrenderer.cpp
@@ -46,7 +46,7 @@ void QQuickMapboxGLRenderer::synchronize(QQuickFramebufferObject *item)
auto quickMap = qobject_cast<QQuickMapboxGL*>(item);
if (!m_initialized) {
QObject::connect(m_map.data(), &QMapboxGL::needsRendering, quickMap, &QQuickMapboxGL::update);
- QObject::connect(m_map.data(), SIGNAL(mapChanged(QMapbox::MapChange)), quickMap, SLOT(onMapChanged(QMapbox::MapChange)));
+ QObject::connect(m_map.data(), SIGNAL(mapChanged(QMapboxGL::MapChange)), quickMap, SLOT(onMapChanged(QMapboxGL::MapChange)));
QObject::connect(this, &QQuickMapboxGLRenderer::centerChanged, quickMap, &QQuickMapboxGL::setCenter);
m_initialized = true;
}
@@ -88,7 +88,7 @@ void QQuickMapboxGLRenderer::synchronize(QQuickFramebufferObject *item)
}
for (const auto& change : quickMap->m_sourceChanges) {
- m_map->addSource(change.value("id").toString(), change);
+ m_map->updateSource(change.value("id").toString(), change);
}
quickMap->m_sourceChanges.clear();
diff --git a/platform/qt/src/qt_conversion.hpp b/platform/qt/src/qt_conversion.hpp
index acb7ed7d54..e49b6dbe3e 100644
--- a/platform/qt/src/qt_conversion.hpp
+++ b/platform/qt/src/qt_conversion.hpp
@@ -94,9 +94,9 @@ inline optional<Value> toValue(const QVariant& value) {
} else if (value.type() == QVariant::Color) {
return { value.value<QColor>().name().toStdString() };
} else if (value.type() == QVariant::Int) {
- return { value.toInt() };
+ return { int64_t(value.toInt()) };
} else if (value.canConvert(QVariant::Double)) {
- return { value.toFloat() };
+ return { value.toDouble() };
} else {
return {};
}
diff --git a/platform/qt/src/run_loop_impl.hpp b/platform/qt/src/run_loop_impl.hpp
index ea64e4b977..c1fe8578e3 100644
--- a/platform/qt/src/run_loop_impl.hpp
+++ b/platform/qt/src/run_loop_impl.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/run_loop.hpp>
diff --git a/platform/qt/src/string_stdlib.cpp b/platform/qt/src/string_stdlib.cpp
index c4adecea06..635a01352e 100644
--- a/platform/qt/src/string_stdlib.cpp
+++ b/platform/qt/src/string_stdlib.cpp
@@ -1,4 +1,4 @@
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/platform.hpp>
#include <QByteArray>
#include <QString>
diff --git a/platform/qt/test/headless_backend_qt.cpp b/platform/qt/test/headless_backend_qt.cpp
index 3f287ae578..1992cab2fa 100644
--- a/platform/qt/test/headless_backend_qt.cpp
+++ b/platform/qt/test/headless_backend_qt.cpp
@@ -1,5 +1,4 @@
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/gl/headless_backend.hpp>
#include <QApplication>
#include <QGLContext>
@@ -9,8 +8,22 @@
#include <QOpenGLContext>
#endif
+#include <cassert>
+
namespace mbgl {
+struct QtImpl : public HeadlessBackend::Impl {
+ void activateContext() final {
+ widget.makeCurrent();
+ }
+
+ void deactivateContext() final {
+ widget.doneCurrent();
+ }
+
+ QGLWidget widget;
+};
+
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
#if QT_VERSION >= 0x050000
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
@@ -21,26 +34,20 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) {
#endif
}
+bool HeadlessBackend::hasDisplay() {
+ return true;
+};
+
void HeadlessBackend::createContext() {
+ assert(!hasContext());
+
static const char* argv[] = { "mbgl" };
static int argc = 1;
static auto* app = new QApplication(argc, const_cast<char**>(argv));
Q_UNUSED(app);
- glContext = new QGLWidget;
-}
-
-void HeadlessBackend::destroyContext() {
- delete glContext;
-}
-
-void HeadlessBackend::activateContext() {
- glContext->makeCurrent();
-}
-
-void HeadlessBackend::deactivateContext() {
- glContext->doneCurrent();
+ impl.reset(new QtImpl);
}
} // namespace mbgl
diff --git a/platform/qt/test/qmapboxgl.cpp b/platform/qt/test/qmapboxgl.cpp
index 597aef5df3..9406fa2420 100644
--- a/platform/qt/test/qmapboxgl.cpp
+++ b/platform/qt/test/qmapboxgl.cpp
@@ -11,8 +11,8 @@ class QMapboxGLTest : public QObject, public ::testing::Test {
public:
QMapboxGLTest() : app(argc, const_cast<char**>(&argv)), map(nullptr, settings) {
- connect(&map, SIGNAL(mapChanged(QMapbox::MapChange)),
- this, SLOT(onMapChanged(QMapbox::MapChange)));
+ connect(&map, SIGNAL(mapChanged(QMapboxGL::MapChange)),
+ this, SLOT(onMapChanged(QMapboxGL::MapChange)));
connect(&map, SIGNAL(needsRendering()),
this, SLOT(onNeedsRendering()));
@@ -23,8 +23,8 @@ public:
map.setCoordinateZoom(QMapbox::Coordinate(60.170448, 24.942046), 14);
}
- void runUntil(QMapbox::MapChange status) {
- changeCallback = [&](QMapbox::MapChange change) {
+ void runUntil(QMapboxGL::MapChange status) {
+ changeCallback = [&](QMapboxGL::MapChange change) {
if (change == status) {
app.exit();
changeCallback = nullptr;
@@ -45,10 +45,10 @@ protected:
QMapboxGLSettings settings;
QMapboxGL map;
- std::function<void(QMapbox::MapChange)> changeCallback;
+ std::function<void(QMapboxGL::MapChange)> changeCallback;
private slots:
- void onMapChanged(QMapbox::MapChange change) {
+ void onMapChanged(QMapboxGL::MapChange change) {
if (changeCallback) {
changeCallback(change);
}
@@ -65,16 +65,16 @@ TEST_F(QMapboxGLTest, TEST_DISABLED_ON_CI(styleJson)) {
map.setStyleJson(json);
ASSERT_EQ(map.styleJson(), json);
- runUntil(QMapbox::MapChangeDidFinishLoadingMap);
+ runUntil(QMapboxGL::MapChangeDidFinishLoadingMap);
map.setStyleJson("invalid json");
- runUntil(QMapbox::MapChangeDidFailLoadingMap);
+ runUntil(QMapboxGL::MapChangeDidFailLoadingMap);
map.setStyleJson("\"\"");
- runUntil(QMapbox::MapChangeDidFailLoadingMap);
+ runUntil(QMapboxGL::MapChangeDidFailLoadingMap);
map.setStyleJson(QString());
- runUntil(QMapbox::MapChangeDidFailLoadingMap);
+ runUntil(QMapboxGL::MapChangeDidFailLoadingMap);
}
TEST_F(QMapboxGLTest, TEST_DISABLED_ON_CI(styleUrl)) {
@@ -82,13 +82,13 @@ TEST_F(QMapboxGLTest, TEST_DISABLED_ON_CI(styleUrl)) {
map.setStyleUrl(url);
ASSERT_EQ(map.styleUrl(), url);
- runUntil(QMapbox::MapChangeDidFinishLoadingMap);
+ runUntil(QMapboxGL::MapChangeDidFinishLoadingMap);
map.setStyleUrl("invalid://url");
- runUntil(QMapbox::MapChangeDidFailLoadingMap);
+ runUntil(QMapboxGL::MapChangeDidFailLoadingMap);
map.setStyleUrl(QString());
- runUntil(QMapbox::MapChangeDidFailLoadingMap);
+ runUntil(QMapboxGL::MapChangeDidFailLoadingMap);
}
#include "qmapboxgl.moc"
diff --git a/scripts/build-shaders.js b/scripts/build-shaders.js
index 9090f19e6d..d00762acf0 100755
--- a/scripts/build-shaders.js
+++ b/scripts/build-shaders.js
@@ -4,68 +4,57 @@ var path = require('path');
var fs = require('fs');
var mkdirp = require('mkdirp');
-var input_file = process.argv[2]
-var output_file = process.argv[3];
+var shaderName = process.argv[2];
+var inputPath = process.argv[3];
+var outputPath = process.argv[4];
-if (!input_file || !output_file) {
- console.warn('No input or output file given.');
- console.warn('Usage: %s [input.vertex.glsl] [output.vertex.hpp]', path.basename(process.argv[1]));
+if (!shaderName || !inputPath || !outputPath) {
+ console.warn('Not enough arguments.');
+ console.warn('Usage: %s shaderName /path-to-shader-sources /output-path', path.basename(process.argv[1]));
process.exit(1);
}
-var components = path.basename(input_file).split('.');
+var pragmaMapboxRe = /(\s*)#pragma\s+mapbox\s*:\s+(define|initialize)\s+(low|medium|high)p\s+(float|vec(?:2|3|4))\s+(.*)/;
-var shader_name = components[0];
-var shader_type = components[1];
-var extension = components[2];
-var data = fs.readFileSync(input_file, 'utf8');
-
-// Replace uniform pragmas
-
-var pragma_mapbox_regex = /(\s*)#pragma\s+mapbox\s*:\s+(define|initialize)\s+(low|medium|high)p\s+(float|vec(?:2|3|4))\s+(.*)/;
-
-var data = data.split('\n').map(function(line) {
- var params = line.match(pragma_mapbox_regex);
- if (params) {
- if (params[2] === 'define') {
- return params[1] + 'uniform ' + params[3] + 'p ' + params[4] + ' u_' + params[5] + ';';
+function applyPragmas(source) {
+ return '\n' + source.split('\n').map(function(line) {
+ var params = line.match(pragmaMapboxRe);
+ if (params) {
+ if (params[2] === 'define') {
+ return params[1] + 'uniform ' + params[3] + 'p ' + params[4] + ' u_' + params[5] + ';';
+ } else {
+ return params[1] + params[3] + 'p ' + params[4] + ' ' + params[5] + ' = u_' + params[5] + ';';
+ }
} else {
- return params[1] + params[3] + 'p ' + params[4] + ' ' + params[5] + ' = u_' + params[5] + ';';
+ return line;
}
- } else {
- return line;
- }
-}).join('\n');
-
-
-var content =
- '#pragma once\n' +
- '\n' +
- '// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.\n' +
- '\n' +
- '#include <mbgl/gl/gl.hpp>\n' +
- '\n' +
- 'namespace mbgl {\n' +
- 'namespace shaders {\n' +
- 'namespace ' + shader_name + ' {\n' +
- '\n' +
- '#ifndef MBGL_SHADER_NAME_' + shader_name.toUpperCase() + '\n' +
- '#define MBGL_SHADER_NAME_' + shader_name.toUpperCase() + '\n' +
- 'constexpr const char* name = "' + shader_name + '";\n' +
- '#endif // MBGL_SHADER_NAME_' + shader_name.toUpperCase() + '\n' +
- '\n' +
- 'constexpr const char* ' + shader_type + ' =\n' +
- '#ifdef GL_ES_VERSION_2_0\n' +
- ' "precision highp float;"\n' +
- '#else\n' +
- ' "#version 120"\n' +
- '#endif\n' +
- ' R"MBGL_SHADER(\n' + data + ')MBGL_SHADER";\n' +
- '\n' +
- '} // namespace ' + shader_name + '\n' +
- '} // namespace shaders\n' +
- '} // namespace mbgl\n';
+ }).join('\n');
+}
-mkdirp.sync(path.dirname(output_file));
-fs.writeFileSync(output_file, content);
+var vertexPrelude = fs.readFileSync(path.join(inputPath, '_prelude.vertex.glsl'));
+var fragmentPrelude = fs.readFileSync(path.join(inputPath, '_prelude.fragment.glsl'));
+var vertexSource = vertexPrelude + fs.readFileSync(path.join(inputPath, shaderName + '.vertex.glsl'), 'utf8');
+var fragmentSource = fragmentPrelude + fs.readFileSync(path.join(inputPath, shaderName + '.fragment.glsl'), 'utf8');
+
+var content = "#pragma once\n" +
+"\n" +
+"// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.\n" +
+"\n" +
+"#include <mbgl/gl/gl.hpp>\n" +
+"\n" +
+"namespace mbgl {\n" +
+"namespace shaders {\n" +
+"\n" +
+"class " + shaderName + " {\n" +
+"public:\n" +
+" static constexpr const char* name = \"" + shaderName + "\";\n" +
+" static constexpr const char* vertexSource = R\"MBGL_SHADER(" + applyPragmas(vertexSource) + ")MBGL_SHADER\";\n" +
+" static constexpr const char* fragmentSource = R\"MBGL_SHADER(" + applyPragmas(fragmentSource) + ")MBGL_SHADER\";\n" +
+"};\n" +
+"\n" +
+"} // namespace shaders\n" +
+"} // namespace mbgl\n";
+
+mkdirp.sync(outputPath);
+fs.writeFileSync(path.join(outputPath, shaderName + '.hpp'), content);
diff --git a/scripts/clang-tools.sh b/scripts/clang-tools.sh
index fa9825f4a4..ae3a5fa0e7 100755
--- a/scripts/clang-tools.sh
+++ b/scripts/clang-tools.sh
@@ -5,8 +5,8 @@ set -o pipefail
export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason"
-CLANG_TIDY=${CLANG_TIDY:-$(mason prefix clang-tidy 3.8.0)/bin/clang-tidy}
-CLANG_FORMAT=${CLANG_FORMAT:-$(mason prefix clang-format 3.8.0)/bin/clang-format}
+CLANG_TIDY=${CLANG_TIDY:-$(mason prefix clang-tidy 3.9.1)/bin/clang-tidy}
+CLANG_FORMAT=${CLANG_FORMAT:-$(mason prefix clang-format 3.9.1)/bin/clang-format}
command -v ${CLANG_TIDY} >/dev/null 2>&1 || {
echo "Can't find ${CLANG_TIDY} in PATH."
@@ -45,17 +45,12 @@ export -f check_tidy check_format
echo "Running clang checks... (this might take a while)"
if [[ -n $2 ]] && [[ $2 == "--diff" ]]; then
- git diff-index --quiet HEAD || {
- echo "Your repository contains unstaged and/or uncommitted changes."
- echo "Please commit all changes before proceeding."
- exit 1
- }
- DIFF_FILES=$(for file in `git diff origin/master..HEAD --name-only | grep "pp$"`; do echo $file; done)
+ DIFF_FILES=$(for file in `git diff origin/master --name-only | grep "pp$"`; do echo $file; done)
if [[ -n $DIFF_FILES ]]; then
echo "${DIFF_FILES}" | xargs -I{} -P ${JOBS} bash -c 'check_tidy --fix' {}
# XXX disabled until we run clang-format over the entire codebase.
#echo "${DIFF_FILES}" | xargs -I{} -P ${JOBS} bash -c 'check_format' {}
- git diff-index --quiet HEAD || {
+ git diff --quiet || {
echo "Changes were made to source files - please review them before committing."
exit 1
}
diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js
index dcb527e8c9..f2acb12a2a 100644
--- a/scripts/generate-style-code.js
+++ b/scripts/generate-style-code.js
@@ -3,27 +3,17 @@
const fs = require('fs');
const ejs = require('ejs');
const spec = require('mapbox-gl-style-spec').latest;
-var colorParser = require('csscolorparser');
+const colorParser = require('csscolorparser');
+
+require('./style-code');
function parseCSSColor(str) {
- var color = colorParser.parseCSSColor(str);
+ const color = colorParser.parseCSSColor(str);
return [
color[0] / 255 * color[3], color[1] / 255 * color[3], color[2] / 255 * color[3], color[3]
];
}
-global.camelize = function (str) {
- return str.replace(/(?:^|-)(.)/g, function (_, x) {
- return x.toUpperCase();
- });
-}
-
-global.camelizeWithLeadingLowercase = function (str) {
- return str.replace(/-(.)/g, function (_, x) {
- return x.toUpperCase();
- });
-}
-
global.propertyType = function (property) {
if (/-translate-anchor$/.test(property.name)) {
return 'TranslateAnchorType';
@@ -50,7 +40,7 @@ global.propertyType = function (property) {
}
default: throw new Error(`unknown type for ${property.name}`)
}
-}
+};
global.defaultValue = function (property) {
// https://github.com/mapbox/mapbox-gl-native/issues/5258
@@ -74,7 +64,7 @@ global.defaultValue = function (property) {
return `${propertyType(property)}::${camelize(property.default)}`;
}
case 'color':
- var color = parseCSSColor(property.default).join(', ');
+ const color = parseCSSColor(property.default).join(', ');
switch (color) {
case '0, 0, 0, 0':
return '{}';
@@ -95,7 +85,7 @@ global.defaultValue = function (property) {
default:
return property.default;
}
-}
+};
const layerHpp = ejs.compile(fs.readFileSync('include/mbgl/style/layers/layer.hpp.ejs', 'utf8'), {strict: true});
const layerCpp = ejs.compile(fs.readFileSync('src/mbgl/style/layers/layer.cpp.ejs', 'utf8'), {strict: true});
@@ -121,16 +111,21 @@ const layers = Object.keys(spec.layer.type.values).map((type) => {
type: type,
layoutProperties: layoutProperties,
paintProperties: paintProperties,
+ doc: spec.layer.type.values[type].doc,
+ layoutPropertiesByName: spec[`layout_${type}`],
+ paintPropertiesByName: spec[`paint_${type}`],
};
});
for (const layer of layers) {
- fs.writeFileSync(`include/mbgl/style/layers/${layer.type}_layer.hpp`, layerHpp(layer));
- fs.writeFileSync(`src/mbgl/style/layers/${layer.type}_layer.cpp`, layerCpp(layer));
+ const layerFileName = layer.type.replace('-', '_');
+
+ writeIfModified(`include/mbgl/style/layers/${layerFileName}_layer.hpp`, layerHpp(layer));
+ writeIfModified(`src/mbgl/style/layers/${layerFileName}_layer.cpp`, layerCpp(layer));
- fs.writeFileSync(`src/mbgl/style/layers/${layer.type}_layer_properties.hpp`, propertiesHpp(layer));
- fs.writeFileSync(`src/mbgl/style/layers/${layer.type}_layer_properties.cpp`, propertiesCpp(layer));
+ writeIfModified(`src/mbgl/style/layers/${layerFileName}_layer_properties.hpp`, propertiesHpp(layer));
+ writeIfModified(`src/mbgl/style/layers/${layerFileName}_layer_properties.cpp`, propertiesCpp(layer));
}
const propertySettersHpp = ejs.compile(fs.readFileSync('include/mbgl/style/conversion/make_property_setters.hpp.ejs', 'utf8'), {strict: true});
-fs.writeFileSync('include/mbgl/style/conversion/make_property_setters.hpp', propertySettersHpp({layers: layers}));
+writeIfModified('include/mbgl/style/conversion/make_property_setters.hpp', propertySettersHpp({layers: layers}));
diff --git a/scripts/log_binary_size.sh b/scripts/log_binary_size.sh
new file mode 100755
index 0000000000..3c55be15f1
--- /dev/null
+++ b/scripts/log_binary_size.sh
@@ -0,0 +1,42 @@
+#!/usr/bin/env bash
+
+set -e
+set -o pipefail
+set -u
+
+# Logs metrics on binary size to CloudWatch
+
+FILE=$1
+DIMENSIONS=$2
+
+if [ -z "${DIMENSIONS}" ]; then
+ echo "* No dimensions specified for '${FILE}'"
+ exit 1
+fi
+
+function filesize {
+ if [ `uname -s` = 'Darwin' ]; then
+ stat -f%z $1
+ else
+ stat --printf=%s $1
+ fi
+}
+
+if [ -f "${FILE}" ]; then
+ SIZE=`filesize ${FILE}`
+ if [ ${CLOUDWATCH:-} ]; then
+ echo "* Reporting `LC_NUMERIC=en_US printf "%'10.f\n" ${SIZE}` bytes for '${DIMENSIONS}' (${FILE})"
+ aws --region us-east-1 cloudwatch put-metric-data \
+ --namespace "Mapbox/GL" \
+ --metric-name "BinarySize" \
+ --unit "Bytes" \
+ --value ${SIZE} \
+ --dimensions "${DIMENSIONS}"
+
+ ./scripts/publish_binary_size.sh "${DIMENSIONS}"
+ else
+ echo "* Measured `LC_NUMERIC=en_US printf "%'10.f\n" ${SIZE}` bytes for '${DIMENSIONS}' (${FILE})"
+ fi
+else
+ echo "* File '${FILE}' does not exist"
+fi
diff --git a/scripts/publish_binary_size.sh b/scripts/publish_binary_size.sh
new file mode 100755
index 0000000000..d5ab71b8c4
--- /dev/null
+++ b/scripts/publish_binary_size.sh
@@ -0,0 +1,75 @@
+#!/usr/bin/env bash
+
+set -e
+set -o pipefail
+set -u
+
+# Downloads log data from AWS CloudWatch and uploads it as a JSON file to S3 for public access.
+
+function publish_binary_size {
+ local DIMENSIONS=$1
+
+ if [ -z "${DIMENSIONS}" ]; then
+ echo "* No dimensions specified"
+ exit 1
+ fi
+
+ function print_dimensions {
+ for ITEM in ${DIMENSIONS//,/ } ; do
+ echo -n "Name=${ITEM//=/,Value=} "
+ done
+ }
+
+ local DATE_FORMAT="%Y-%m-%dT%H:%M:%SZ"
+ local DATE_END=$(date -u +${DATE_FORMAT})
+
+ if [ `uname -s` = 'Darwin' ]; then # BSD date
+ local DATE_BEGIN=$(date -jf "${DATE_FORMAT}" -v-30d "${DATE_END}" +"${DATE_FORMAT}")
+ else # GNU date
+ local DATE_BEGIN=$(date --date="${DATE_END} - 30 days" +"${DATE_FORMAT}")
+ fi
+
+ # Download the metrics, gzip, and upload to S3.
+ aws --region us-east-1 cloudwatch get-metric-statistics \
+ --namespace "Mapbox/GL" \
+ --metric-name "BinarySize" \
+ --unit "Bytes" \
+ --start-time "${DATE_BEGIN}" \
+ --end-time "${DATE_END}" \
+ --period 3600 \
+ --statistics Maximum \
+ --dimensions `print_dimensions` \
+ | gzip | aws s3 cp \
+ --acl public-read \
+ --cache-control "max-age=300" \
+ --content-encoding gzip \
+ --content-type application/json \
+ - "s3://mapbox/mapbox-gl-native/metrics/binary-size/${DIMENSIONS}.json"
+
+ echo "* Uploaded data to 's3://mapbox/mapbox-gl-native/metrics/binary-size/${DIMENSIONS}.json'"
+}
+
+if [ $# -gt 0 ]; then
+ # Upload the specified dimension only
+ publish_binary_size "$1"
+else
+ # Upload all dimensions that we are tracking
+ publish_binary_size "Platform=iOS,Arch=armv7"
+ publish_binary_size "Platform=iOS,Arch=arm64"
+ publish_binary_size "Platform=iOS,Arch=i386"
+ publish_binary_size "Platform=iOS,Arch=x86_64"
+ publish_binary_size "Platform=iOS,Arch=Dynamic"
+
+ publish_binary_size "Platform=macOS,Arch=x86_64"
+
+ publish_binary_size "Platform=Linux,Compiler=clang-3.8,Arch=x86_64"
+ publish_binary_size "Platform=Linux,Compiler=gcc-5,Arch=x86_64"
+
+ publish_binary_size "Platform=Android,Arch=arm-v5"
+ publish_binary_size "Platform=Android,Arch=arm-v7"
+ publish_binary_size "Platform=Android,Arch=arm-v8"
+ publish_binary_size "Platform=Android,Arch=x86"
+ publish_binary_size "Platform=Android,Arch=x86_64"
+ publish_binary_size "Platform=Android,Arch=mips"
+ publish_binary_size "Platform=Android,Arch=Archive"
+fi
diff --git a/scripts/style-code.js b/scripts/style-code.js
new file mode 100644
index 0000000000..156934a240
--- /dev/null
+++ b/scripts/style-code.js
@@ -0,0 +1,36 @@
+// Global functions //
+
+const fs = require('fs');
+
+global.iff = function (condition, val) {
+ return condition() ? val : "";
+};
+
+global.camelize = function (str) {
+ return str.replace(/(?:^|-)(.)/g, function (_, x) {
+ return x.toUpperCase();
+ });
+};
+
+global.camelizeWithLeadingLowercase = function (str) {
+ return str.replace(/-(.)/g, function (_, x) {
+ return x.toUpperCase();
+ });
+};
+
+global.snakeCaseUpper = function snakeCaseUpper(str) {
+ return str.replace(/-/g, "_").toUpperCase();
+};
+
+global.writeIfModified = function(filename, newContent) {
+ try {
+ const oldContent = fs.readFileSync(filename, 'utf8');
+ if (oldContent == newContent) {
+ console.warn(`* Skipping current file '${filename}'`);
+ return;
+ }
+ } catch(err) {
+ }
+ fs.writeFileSync(filename, newContent);
+ console.warn(`* Updating outdated file '${filename}'`);
+};
diff --git a/scripts/tidy.sh b/scripts/tidy.sh
deleted file mode 100755
index 424c82c3cd..0000000000
--- a/scripts/tidy.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -o pipefail
-
-# Ensure mason is on the PATH
-export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason"
-
-BUILDTYPE=${BUILDTYPE:-Release}
-
-export CLANG_TIDY=clang-tidy-3.8
-
-mapbox_time "config" \
-make config
-
-mapbox_time "tidy" \
-make tidy
diff --git a/scripts/travis_setup.sh b/scripts/travis_setup.sh
index 47df36788d..8551e1cb97 100755
--- a/scripts/travis_setup.sh
+++ b/scripts/travis_setup.sh
@@ -25,7 +25,9 @@ fi
echo "export CXX=\"${CXX}\""
echo "export CC=\"${CC}\""
-${CXX} --version
+if [ -x $(which ${CXX}) ]; then
+ ${CXX} --version
+fi
# Ensure mason is on the PATH
export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason"
@@ -37,20 +39,34 @@ git submodule update --init .mason
mapbox_time "touch_package_json" \
touch package.json
-# Start the mock X server
-if [ -f /etc/init.d/xvfb ] && [ ! -z "${RUN_XVFB}" ]; then
+function mapbox_start_xvfb {
+ if [ ! -f /etc/init.d/xvfb ]; then
+ echo "Error: Could not start Xvfb mock server."
+ exit 1
+ fi
+
mapbox_time "start_xvfb" \
sh -e /etc/init.d/xvfb start
sleep 2 # sometimes, xvfb takes some time to start up
# Make sure we're connecting to xvfb
export DISPLAY=:99.0
+}
+
+export -f mapbox_start_xvfb
+function mapbox_export_mesa_library_path {
+ CXX11ABI=""
+ if [ `scripts/check-cxx11abi.sh` = 'ON' ]; then
+ CXX11ABI="-cxx11abi"
+ fi
# Install and set up to load a more recent version of mesa
mapbox_time "install_mesa" \
- mason install mesa 11.2.2
- export LD_LIBRARY_PATH="`mason prefix mesa 11.2.2`/lib:${LD_LIBRARY_PATH:-}"
-fi
+ mason install mesa 13.0.0-glx${CXX11ABI}
+ export LD_LIBRARY_PATH="`mason prefix mesa 13.0.0-glx${CXX11ABI}`/lib:${LD_LIBRARY_PATH:-}"
+}
+
+export -f mapbox_export_mesa_library_path
# Install and set up to load awscli
pip install --user awscli
diff --git a/scripts/valgrind.sh b/scripts/valgrind.sh
index 4009063c80..c717fc2cb8 100755
--- a/scripts/valgrind.sh
+++ b/scripts/valgrind.sh
@@ -3,7 +3,7 @@
set -e
set -o pipefail
-.mason/mason install valgrind latest
+.mason/mason install valgrind 3.12.0
PARAMS="\
--leak-check=full \
@@ -13,6 +13,6 @@ PARAMS="\
--gen-suppressions=all \
--suppressions=scripts/valgrind.sup"
-export VALGRIND_LIB=$(.mason/mason prefix valgrind latest)/lib/valgrind
+export VALGRIND_LIB=$(.mason/mason prefix valgrind 3.12.0)/lib/valgrind
-$(.mason/mason prefix valgrind latest)/bin/valgrind $PARAMS $@
+$(.mason/mason prefix valgrind 3.12.0)/bin/valgrind $PARAMS $@
diff --git a/scripts/valgrind.sup b/scripts/valgrind.sup
index f21f54be54..ea3e3d635a 100644
--- a/scripts/valgrind.sup
+++ b/scripts/valgrind.sup
@@ -180,3 +180,89 @@
fun:draw_wide_line
...
}
+{
+ Ubuntu 14.04 - Travis + Qt5
+ Memcheck:Leak
+ ...
+ obj:*/libQt5Core.*
+ ...
+}
+{
+ Ubuntu 14.04 - Travis + Qt5
+ Memcheck:Cond
+ ...
+ obj:*/libQt5Core.*
+ ...
+}
+{
+ Ubuntu 14.04 - Travis + Qt5
+ Memcheck:Value8
+ ...
+ obj:*/libQt5Core.*
+ ...
+}
+{
+ Ubuntu 14.04 - Travis + Qt5
+ Memcheck:Leak
+ ...
+ obj:*/libQt5Gui.*
+ ...
+}
+{
+ Ubuntu 14.04 - Travis + Qt5
+ Memcheck:Cond
+ ...
+ obj:*/libQt5Gui.*
+ ...
+}
+{
+ Ubuntu 14.04 - Travis + Qt5
+ Memcheck:Value8
+ ...
+ obj:*/libQt5Gui.*
+ ...
+}
+{
+ Ubuntu 14.04 - Travis + mesa 13.0.0-glx
+ Memcheck:Cond
+ ...
+ obj:*/mesa/libGL.so.*
+ ...
+}
+{
+ Ubuntu 14.04 - Travis + mesa 13.0.0-glx
+ Memcheck:Value8
+ ...
+ obj:*/mesa/libGL.so.*
+ ...
+}
+{
+ Ubuntu 14.04 - Travis + mesa 13.0.0-glx
+ Memcheck:Cond
+ ...
+ fun:do_rasterize_bin
+ ...
+}
+{
+ Ubuntu 14.04 - Travis + mesa 13.0.0-glx
+ Memcheck:Value8
+ ...
+ fun:do_rasterize_bin
+ ...
+}
+{
+ Ubuntu 14.04 - Travis + mesa 13.0.0-glx
+ Memcheck:Cond
+ ...
+ fun:_ZN6mapbox10pixelmatchEPKhS1_mmPhdb
+ ...
+}
+{
+ Ubuntu 14.04 - Travis + mesa 13.0.0-glx
+ Memcheck:Param
+ write(buf)
+ ...
+ obj:*/libc-*
+ fun:_ZN4mbgl4util10write_fileERKSsS2_
+ ...
+}
diff --git a/src/mbgl/algorithm/generate_clip_ids_impl.hpp b/src/mbgl/algorithm/generate_clip_ids_impl.hpp
index ff8f8d3fdf..59ca66bf66 100644
--- a/src/mbgl/algorithm/generate_clip_ids_impl.hpp
+++ b/src/mbgl/algorithm/generate_clip_ids_impl.hpp
@@ -1,8 +1,8 @@
#pragma once
#include <mbgl/algorithm/generate_clip_ids.hpp>
-#include <mbgl/util/math.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/math/log2.hpp>
+#include <mbgl/util/logging.hpp>
namespace mbgl {
namespace algorithm {
@@ -15,6 +15,10 @@ void ClipIDGenerator::update(Renderables& renderables) {
for (auto it = renderables.begin(); it != end; it++) {
auto& tileID = it->first;
auto& renderable = it->second;
+ if (!renderable.used) {
+ continue;
+ }
+
renderable.clip = {};
Leaf leaf{ renderable.clip };
@@ -58,6 +62,9 @@ void ClipIDGenerator::update(Renderables& renderables) {
uint8_t count = 1;
for (auto& pair : renderables) {
auto& renderable = pair.second;
+ if (!renderable.used) {
+ continue;
+ }
renderable.clip.mask |= mask;
// Assign only to clip IDs that have no value yet.
diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp
index dbd5f1f433..f8c1c3adf7 100644
--- a/src/mbgl/annotation/annotation_manager.cpp
+++ b/src/mbgl/annotation/annotation_manager.cpp
@@ -20,7 +20,7 @@ const std::string AnnotationManager::SourceID = "com.mapbox.annotations";
const std::string AnnotationManager::PointLayerID = "com.mapbox.annotations.points";
AnnotationManager::AnnotationManager(float pixelRatio)
- : spriteAtlas(1024, 1024, pixelRatio) {
+ : spriteAtlas({ 1024, 1024 }, pixelRatio) {
struct NullFileSource : public FileSource {
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override {
@@ -232,7 +232,7 @@ void AnnotationManager::removeIcon(const std::string& name) {
double AnnotationManager::getTopOffsetPixelsForIcon(const std::string& name) {
auto sprite = spriteAtlas.getSprite(name);
- return sprite ? -(sprite->image.height / sprite->pixelRatio) / 2 : 0;
+ return sprite ? -(sprite->image.size.height / sprite->pixelRatio) / 2 : 0;
}
} // namespace mbgl
diff --git a/src/mbgl/annotation/annotation_tile.hpp b/src/mbgl/annotation/annotation_tile.hpp
index d43ec82d38..bf73075992 100644
--- a/src/mbgl/annotation/annotation_tile.hpp
+++ b/src/mbgl/annotation/annotation_tile.hpp
@@ -31,7 +31,7 @@ public:
FeatureType getType() const override { return type; }
optional<Value> getValue(const std::string&) const override;
- optional<FeatureIdentifier> getID() const override { return { id }; }
+ optional<FeatureIdentifier> getID() const override { return { static_cast<uint64_t>(id) }; }
GeometryCollection getGeometries() const override { return geometries; }
const AnnotationID id;
diff --git a/src/mbgl/annotation/style_sourced_annotation_impl.cpp b/src/mbgl/annotation/style_sourced_annotation_impl.cpp
index d3212da12d..cb664cf15d 100644
--- a/src/mbgl/annotation/style_sourced_annotation_impl.cpp
+++ b/src/mbgl/annotation/style_sourced_annotation_impl.cpp
@@ -24,12 +24,12 @@ void StyleSourcedAnnotationImpl::updateStyle(Style& style) const {
return;
if (sourceLayer->is<LineLayer>()) {
- std::unique_ptr<Layer> layer = sourceLayer->baseImpl->copy(layerID, "", AnnotationManager::SourceID);
+ std::unique_ptr<Layer> layer = sourceLayer->baseImpl->copy(layerID, AnnotationManager::SourceID);
layer->as<LineLayer>()->setSourceLayer(layerID);
layer->as<LineLayer>()->setVisibility(VisibilityType::Visible);
style.addLayer(std::move(layer), sourceLayer->getID());
} else if (sourceLayer->is<FillLayer>()) {
- std::unique_ptr<Layer> layer = sourceLayer->baseImpl->copy(layerID, "", AnnotationManager::SourceID);
+ std::unique_ptr<Layer> layer = sourceLayer->baseImpl->copy(layerID, AnnotationManager::SourceID);
layer->as<FillLayer>()->setSourceLayer(layerID);
layer->as<FillLayer>()->setVisibility(VisibilityType::Visible);
style.addLayer(std::move(layer), sourceLayer->getID());
diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp
index b37bdb5ecc..5019d888ca 100644
--- a/src/mbgl/geometry/feature_index.cpp
+++ b/src/mbgl/geometry/feature_index.cpp
@@ -59,7 +59,8 @@ void FeatureIndex::query(
const optional<std::vector<std::string>>& filterLayerIDs,
const GeometryTileData& geometryTileData,
const CanonicalTileID& tileID,
- const style::Style& style) const {
+ const style::Style& style,
+ const CollisionTile* collisionTile) const {
mapbox::geometry::box<int16_t> box = mapbox::geometry::envelope(queryGeometry);
@@ -150,12 +151,8 @@ optional<GeometryCoordinates> FeatureIndex::translateQueryGeometry(
return translated;
}
-void FeatureIndex::addBucketLayerName(const std::string& bucketName, const std::string& layerID) {
- bucketLayerIDs[bucketName].push_back(layerID);
-}
-
-void FeatureIndex::setCollisionTile(std::unique_ptr<CollisionTile> collisionTile_) {
- collisionTile = std::move(collisionTile_);
+void FeatureIndex::setBucketLayerIDs(const std::string& bucketName, const std::vector<std::string>& layerIDs) {
+ bucketLayerIDs[bucketName] = layerIDs;
}
} // namespace mbgl
diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp
index 021770c78d..ca813f4b6b 100644
--- a/src/mbgl/geometry/feature_index.hpp
+++ b/src/mbgl/geometry/feature_index.hpp
@@ -42,7 +42,8 @@ public:
const optional<std::vector<std::string>>& layerIDs,
const GeometryTileData&,
const CanonicalTileID&,
- const style::Style&) const;
+ const style::Style&,
+ const CollisionTile*) const;
static optional<GeometryCoordinates> translateQueryGeometry(
const GeometryCoordinates& queryGeometry,
@@ -51,9 +52,7 @@ public:
const float bearing,
const float pixelsToTileUnits);
- void addBucketLayerName(const std::string& bucketName, const std::string& layerName);
-
- void setCollisionTile(std::unique_ptr<CollisionTile>);
+ void setBucketLayerIDs(const std::string& bucketName, const std::vector<std::string>& layerIDs);
private:
void addFeature(
@@ -67,7 +66,6 @@ private:
const float bearing,
const float pixelsToTileUnits) const;
- std::unique_ptr<CollisionTile> collisionTile;
GridIndex<IndexedSubfeature> grid;
unsigned int sortIndex = 0;
diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp
index 50e82cc015..71a855b943 100644
--- a/src/mbgl/geometry/line_atlas.cpp
+++ b/src/mbgl/geometry/line_atlas.cpp
@@ -1,8 +1,7 @@
#include <mbgl/geometry/line_atlas.hpp>
-#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/context.hpp>
-#include <mbgl/platform/log.hpp>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/logging.hpp>
+#include <mbgl/util/platform.hpp>
#include <boost/functional/hash.hpp>
@@ -11,10 +10,8 @@
namespace mbgl {
-LineAtlas::LineAtlas(uint16_t w, uint16_t h)
- : width(w),
- height(h),
- data(std::make_unique<char[]>(w * h)),
+LineAtlas::LineAtlas(const Size size)
+ : image(size),
dirty(true) {
}
@@ -40,11 +37,11 @@ LinePatternPos LineAtlas::getDashPosition(const std::vector<float>& dasharray,
}
LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatternCap patternCap) {
- int n = patternCap == LinePatternCap::Round ? 7 : 0;
- int dashheight = 2 * n + 1;
+ const uint8_t n = patternCap == LinePatternCap::Round ? 7 : 0;
+ const uint8_t dashheight = 2 * n + 1;
const uint8_t offset = 128;
- if (nextRow + dashheight > height) {
+ if (nextRow + dashheight > image.size.height) {
Log::Warning(Event::OpenGL, "line atlas bitmap overflow");
return LinePatternPos();
}
@@ -54,7 +51,7 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
length += part;
}
- float stretch = width / length;
+ float stretch = image.size.width / length;
float halfWidth = stretch * 0.5;
// If dasharray has an odd length, both the first and last parts
// are dashes and should be joined seamlessly.
@@ -62,7 +59,7 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
for (int y = -n; y <= n; y++) {
int row = nextRow + n + y;
- int index = width * row;
+ int index = image.size.width * row;
float left = 0;
float right = dasharray[0];
@@ -72,7 +69,7 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
left -= dasharray.back();
}
- for (int x = 0; x < width; x++) {
+ for (uint32_t x = 0; x < image.size.width; x++) {
while (right < x / stretch) {
left = right;
@@ -104,13 +101,13 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
signedDistance = int((inside ? 1 : -1) * dist);
}
- data[index + x] = fmax(0, fmin(255, signedDistance + offset));
+ image.data[index + x] = fmax(0, fmin(255, signedDistance + offset));
}
}
LinePatternPos position;
- position.y = (0.5 + nextRow + n) / height;
- position.height = (2.0 * n) / height;
+ position.y = (0.5 + nextRow + n) / image.size.height;
+ position.height = (2.0 * n) / image.size.height;
position.width = length;
nextRow += dashheight;
@@ -120,59 +117,24 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
return position;
}
-void LineAtlas::upload(gl::Context& context, gl::TextureUnit unit) {
- if (dirty) {
- bind(context, unit);
- }
+Size LineAtlas::getSize() const {
+ return image.size;
}
-void LineAtlas::bind(gl::Context& context, gl::TextureUnit unit) {
- bool first = false;
+void LineAtlas::upload(gl::Context& context, gl::TextureUnit unit) {
if (!texture) {
- texture = context.createTexture();
- context.activeTexture = unit;
- context.texture[unit] = *texture;
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- first = true;
- } else if (context.texture[unit] != *texture) {
- context.activeTexture = unit;
- context.texture[unit] = *texture;
+ texture = context.createTexture(image, unit);
+ } else if (dirty) {
+ context.updateTexture(*texture, image, unit);
}
- if (dirty) {
- context.activeTexture = unit;
- if (first) {
- MBGL_CHECK_ERROR(glTexImage2D(
- GL_TEXTURE_2D, // GLenum target
- 0, // GLint level
- GL_ALPHA, // GLint internalformat
- width, // GLsizei width
- height, // GLsizei height
- 0, // GLint border
- GL_ALPHA, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- data.get() // const GLvoid * data
- ));
- } else {
- MBGL_CHECK_ERROR(glTexSubImage2D(
- GL_TEXTURE_2D, // GLenum target
- 0, // GLint level
- 0, // GLint xoffset
- 0, // GLint yoffset
- width, // GLsizei width
- height, // GLsizei height
- GL_ALPHA, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- data.get() // const GLvoid *pixels
- ));
- }
-
+ dirty = false;
+}
- dirty = false;
- }
+void LineAtlas::bind(gl::Context& context, gl::TextureUnit unit) {
+ upload(context, unit);
+ context.bindTexture(*texture, unit, gl::TextureFilter::Linear, gl::TextureMipMap::No,
+ gl::TextureWrap::Repeat, gl::TextureWrap::Clamp);
}
} // namespace mbgl
diff --git a/src/mbgl/geometry/line_atlas.hpp b/src/mbgl/geometry/line_atlas.hpp
index e974b4ff02..b1e7a670c1 100644
--- a/src/mbgl/geometry/line_atlas.hpp
+++ b/src/mbgl/geometry/line_atlas.hpp
@@ -1,6 +1,8 @@
#pragma once
+#include <mbgl/gl/texture.hpp>
#include <mbgl/gl/object.hpp>
+#include <mbgl/util/image.hpp>
#include <mbgl/util/optional.hpp>
#include <vector>
@@ -13,11 +15,12 @@ namespace gl {
class Context;
} // namespace gl
-typedef struct {
+class LinePatternPos {
+public:
float width;
float height;
float y;
-} LinePatternPos;
+};
enum class LinePatternCap : bool {
Square = false,
@@ -26,7 +29,7 @@ enum class LinePatternCap : bool {
class LineAtlas {
public:
- LineAtlas(uint16_t width, uint16_t height);
+ LineAtlas(Size);
~LineAtlas();
// Binds the atlas texture to the GPU, and uploads data if it is out of date.
@@ -39,14 +42,13 @@ public:
LinePatternPos getDashPosition(const std::vector<float>&, LinePatternCap);
LinePatternPos addDash(const std::vector<float>& dasharray, LinePatternCap);
- const uint16_t width;
- const uint16_t height;
+ Size getSize() const;
private:
- const std::unique_ptr<char[]> data;
+ const AlphaImage image;
bool dirty;
- mbgl::optional<gl::UniqueTexture> texture;
- int nextRow = 0;
+ mbgl::optional<gl::Texture> texture;
+ uint32_t nextRow = 0;
std::unordered_map<size_t, LinePatternPos> positions;
};
diff --git a/src/mbgl/gl/attribute.cpp b/src/mbgl/gl/attribute.cpp
new file mode 100644
index 0000000000..7432fff590
--- /dev/null
+++ b/src/mbgl/gl/attribute.cpp
@@ -0,0 +1,29 @@
+#include <mbgl/gl/attribute.hpp>
+#include <mbgl/gl/gl.hpp>
+
+namespace mbgl {
+namespace gl {
+
+AttributeLocation bindAttributeLocation(ProgramID id, AttributeLocation location, const char* name) {
+ MBGL_CHECK_ERROR(glBindAttribLocation(id, location, name));
+ return location;
+}
+
+void bindAttribute(AttributeLocation location,
+ std::size_t count,
+ DataType type,
+ std::size_t vertexSize,
+ std::size_t vertexOffset,
+ std::size_t attributeOffset) {
+ MBGL_CHECK_ERROR(glEnableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttribPointer(
+ location,
+ static_cast<GLint>(count),
+ static_cast<GLenum>(type),
+ GL_FALSE,
+ static_cast<GLsizei>(vertexSize),
+ reinterpret_cast<GLvoid*>(attributeOffset + (vertexSize * vertexOffset))));
+}
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp
index 8bc474e967..e45014127b 100644
--- a/src/mbgl/gl/attribute.hpp
+++ b/src/mbgl/gl/attribute.hpp
@@ -1,50 +1,171 @@
#pragma once
#include <mbgl/gl/types.hpp>
-#include <mbgl/gl/shader.hpp>
+#include <mbgl/util/ignore.hpp>
+#include <mbgl/util/indexed_tuple.hpp>
#include <cstddef>
-#include <limits>
-#include <vector>
+#include <functional>
namespace mbgl {
namespace gl {
-template <typename T, std::size_t N>
+template <class Tag, class T, std::size_t N>
class Attribute {
public:
- Attribute(const char* name, const Shader& shader)
- : location(shader.getAttributeLocation(name)) {}
+ using Type = T[N];
- AttributeLocation location;
+ class State {
+ public:
+ explicit State(AttributeLocation location_)
+ : location(location_) {}
+
+ AttributeLocation location;
+ static constexpr std::size_t count = N;
+ static constexpr DataType type = DataTypeOf<T>::value;
+ };
};
-class AttributeBinding {
+#define MBGL_DEFINE_ATTRIBUTE(type_, n_, name_) \
+ struct name_ : ::mbgl::gl::Attribute<name_, type_, n_> { static constexpr auto name = #name_; }
+
+namespace detail {
+
+// Attribute binding requires member offsets. The only standard way to
+// obtain an offset is the offsetof macro. The offsetof macro has defined
+// behavior only for standard layout types. That rules out std::tuple and
+// any other solution that relies on chained inheritance. Manually implemented
+// variadic specialization looks like the only solution. Fortunately, we
+// only use a maximum of five attributes.
+
+template <class... As>
+class Vertex;
+
+template <class A1>
+class Vertex<A1> {
public:
- template <class Vertex, class T, std::size_t N, std::size_t O>
- AttributeBinding(const T (Vertex::*)[N], const Attribute<T, N>& attribute, std::integral_constant<std::size_t, O>)
- : location(attribute.location),
- type(DataTypeOf<T>::value),
- count(N),
- offset(O) {
- static_assert(std::is_standard_layout<Vertex>::value, "vertex type must use standard layout");
- static_assert(O % 4 == 0, "vertex attribute must be optimally aligned");
- static_assert(1 <= N && N <= 4, "count must be 1, 2, 3, or 4");
- static_assert(sizeof(Vertex) <= std::numeric_limits<int32_t>::max(), "vertex type is too big");
- }
+ typename A1::Type a1;
- AttributeLocation location;
- DataType type;
- uint8_t count;
- std::size_t offset;
+ using VertexType = Vertex<A1>;
+ static const std::size_t attributeOffsets[1];
};
-#define MBGL_MAKE_ATTRIBUTE_BINDING(Vertex, shader, name) \
- ::mbgl::gl::AttributeBinding(&Vertex::name, \
- shader.name, \
- std::integral_constant<std::size_t, offsetof(Vertex, name)>())
+template <class A1, class A2>
+class Vertex<A1, A2> {
+public:
+ typename A1::Type a1;
+ typename A2::Type a2;
+
+ using VertexType = Vertex<A1, A2>;
+ static const std::size_t attributeOffsets[2];
+};
+
+template <class A1, class A2, class A3>
+class Vertex<A1, A2, A3> {
+public:
+ typename A1::Type a1;
+ typename A2::Type a2;
+ typename A3::Type a3;
+
+ using VertexType = Vertex<A1, A2, A3>;
+ static const std::size_t attributeOffsets[3];
+};
+
+template <class A1, class A2, class A3, class A4>
+class Vertex<A1, A2, A3, A4> {
+public:
+ typename A1::Type a1;
+ typename A2::Type a2;
+ typename A3::Type a3;
+ typename A4::Type a4;
+
+ using VertexType = Vertex<A1, A2, A3, A4>;
+ static const std::size_t attributeOffsets[4];
+};
+
+template <class A1, class A2, class A3, class A4, class A5>
+class Vertex<A1, A2, A3, A4, A5> {
+public:
+ typename A1::Type a1;
+ typename A2::Type a2;
+ typename A3::Type a3;
+ typename A4::Type a4;
+ typename A5::Type a5;
+
+ using VertexType = Vertex<A1, A2, A3, A4, A5>;
+ static const std::size_t attributeOffsets[5];
+};
-template <class Shader, class Vertex> struct AttributeBindings;
+template <class A1>
+const std::size_t Vertex<A1>::attributeOffsets[1] = {
+ offsetof(VertexType, a1)
+};
+
+template <class A1, class A2>
+const std::size_t Vertex<A1, A2>::attributeOffsets[2] = {
+ offsetof(VertexType, a1),
+ offsetof(VertexType, a2)
+};
+
+template <class A1, class A2, class A3>
+const std::size_t Vertex<A1, A2, A3>::attributeOffsets[3] = {
+ offsetof(VertexType, a1),
+ offsetof(VertexType, a2),
+ offsetof(VertexType, a3)
+};
+
+template <class A1, class A2, class A3, class A4>
+const std::size_t Vertex<A1, A2, A3, A4>::attributeOffsets[4] = {
+ offsetof(VertexType, a1),
+ offsetof(VertexType, a2),
+ offsetof(VertexType, a3),
+ offsetof(VertexType, a4)
+};
+
+template <class A1, class A2, class A3, class A4, class A5>
+const std::size_t Vertex<A1, A2, A3, A4, A5>::attributeOffsets[5] = {
+ offsetof(VertexType, a1),
+ offsetof(VertexType, a2),
+ offsetof(VertexType, a3),
+ offsetof(VertexType, a4),
+ offsetof(VertexType, a5)
+};
+
+} // namespace detail
+
+AttributeLocation bindAttributeLocation(ProgramID, AttributeLocation, const char * name);
+
+void bindAttribute(AttributeLocation location,
+ std::size_t count,
+ DataType type,
+ std::size_t vertexSize,
+ std::size_t vertexOffset,
+ std::size_t attributeOffset);
+
+template <class... As>
+class Attributes {
+public:
+ using State = IndexedTuple<TypeList<As...>, TypeList<typename As::State...>>;
+ using Vertex = detail::Vertex<As...>;
+
+ template <class A>
+ static constexpr std::size_t Index = TypeIndex<A, As...>::value;
+
+ static State state(const ProgramID& id) {
+ return State { typename As::State(bindAttributeLocation(id, Index<As>, As::name))... };
+ }
+
+ static std::function<void (std::size_t)> binder(const State& state) {
+ return [&state] (std::size_t vertexOffset) {
+ util::ignore({ (bindAttribute(state.template get<As>().location,
+ state.template get<As>().count,
+ state.template get<As>().type,
+ sizeof(Vertex),
+ vertexOffset,
+ Vertex::attributeOffsets[Index<As>]), 0)... });
+ };
+ }
+};
} // namespace gl
} // namespace mbgl
diff --git a/src/mbgl/gl/color_mode.cpp b/src/mbgl/gl/color_mode.cpp
new file mode 100644
index 0000000000..e838c8e2ff
--- /dev/null
+++ b/src/mbgl/gl/color_mode.cpp
@@ -0,0 +1,44 @@
+#include <mbgl/gl/color_mode.hpp>
+#include <mbgl/gl/gl.hpp>
+#include <mbgl/util/traits.hpp>
+
+namespace mbgl {
+namespace gl {
+
+static_assert(underlying_type(ColorMode::BlendEquation::Add) == GL_FUNC_ADD, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::BlendEquation::Subtract) == GL_FUNC_SUBTRACT, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::BlendEquation::ReverseSubtract) == GL_FUNC_REVERSE_SUBTRACT, "OpenGL enum mismatch");
+
+static_assert(underlying_type(ColorMode::Zero) == GL_ZERO, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::One) == GL_ONE, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::SrcColor) == GL_SRC_COLOR, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::OneMinusSrcColor) == GL_ONE_MINUS_SRC_COLOR, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::DstColor) == GL_DST_COLOR, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::OneMinusDstColor) == GL_ONE_MINUS_DST_COLOR, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::SrcAlpha) == GL_SRC_ALPHA, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::OneMinusSrcAlpha) == GL_ONE_MINUS_SRC_ALPHA, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::DstAlpha) == GL_DST_ALPHA, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::OneMinusDstAlpha) == GL_ONE_MINUS_DST_ALPHA, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::ConstantColor) == GL_CONSTANT_COLOR, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::OneMinusConstantColor) == GL_ONE_MINUS_CONSTANT_COLOR, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::ConstantAlpha) == GL_CONSTANT_ALPHA, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::OneMinusConstantAlpha) == GL_ONE_MINUS_CONSTANT_ALPHA, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::SrcAlphaSaturate) == GL_SRC_ALPHA_SATURATE, "OpenGL enum mismatch");
+
+static_assert(underlying_type(ColorMode::Zero) == GL_ZERO, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::One) == GL_ONE, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::SrcColor) == GL_SRC_COLOR, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::OneMinusSrcColor) == GL_ONE_MINUS_SRC_COLOR, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::DstColor) == GL_DST_COLOR, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::OneMinusDstColor) == GL_ONE_MINUS_DST_COLOR, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::SrcAlpha) == GL_SRC_ALPHA, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::OneMinusSrcAlpha) == GL_ONE_MINUS_SRC_ALPHA, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::DstAlpha) == GL_DST_ALPHA, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::OneMinusDstAlpha) == GL_ONE_MINUS_DST_ALPHA, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::ConstantColor) == GL_CONSTANT_COLOR, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::OneMinusConstantColor) == GL_ONE_MINUS_CONSTANT_COLOR, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::ConstantAlpha) == GL_CONSTANT_ALPHA, "OpenGL enum mismatch");
+static_assert(underlying_type(ColorMode::OneMinusConstantAlpha) == GL_ONE_MINUS_CONSTANT_ALPHA, "OpenGL enum mismatch");
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/color_mode.hpp b/src/mbgl/gl/color_mode.hpp
new file mode 100644
index 0000000000..e73c8737eb
--- /dev/null
+++ b/src/mbgl/gl/color_mode.hpp
@@ -0,0 +1,95 @@
+#pragma once
+
+#include <mbgl/util/variant.hpp>
+#include <mbgl/util/color.hpp>
+
+namespace mbgl {
+namespace gl {
+
+class ColorMode {
+public:
+ enum class BlendEquation {
+ Add = 0x8006,
+ Subtract = 0x800A,
+ ReverseSubtract = 0x800B
+ };
+
+ enum BlendFactor {
+ Zero = 0x0000,
+ One = 0x0001,
+ SrcColor = 0x0300,
+ OneMinusSrcColor = 0x0301,
+ SrcAlpha = 0x0302,
+ OneMinusSrcAlpha = 0x0303,
+ DstAlpha = 0x0304,
+ OneMinusDstAlpha = 0x0305,
+ DstColor = 0x0306,
+ OneMinusDstColor = 0x0307,
+ SrcAlphaSaturate = 0x0308,
+ ConstantColor = 0x8001,
+ OneMinusConstantColor = 0x8002,
+ ConstantAlpha = 0x8003,
+ OneMinusConstantAlpha = 0x8004
+ };
+
+ template <BlendEquation E>
+ struct ConstantBlend {
+ static constexpr BlendEquation equation = E;
+ static constexpr BlendFactor srcFactor = One;
+ static constexpr BlendFactor dstFactor = One;
+ };
+
+ template <BlendEquation E>
+ struct LinearBlend {
+ static constexpr BlendEquation equation = E;
+ BlendFactor srcFactor;
+ BlendFactor dstFactor;
+ };
+
+ struct Replace {
+ static constexpr BlendEquation equation = BlendEquation::Add;
+ static constexpr BlendFactor srcFactor = One;
+ static constexpr BlendFactor dstFactor = One;
+ };
+
+ using Add = LinearBlend<BlendEquation::Add>;
+ using Subtract = LinearBlend<BlendEquation::Subtract>;
+ using ReverseSubtract = LinearBlend<BlendEquation::ReverseSubtract>;
+
+ using BlendFunction = variant<
+ Replace,
+ Add,
+ Subtract,
+ ReverseSubtract>;
+
+ BlendFunction blendFunction;
+ Color blendColor;
+
+ struct Mask {
+ bool r;
+ bool g;
+ bool b;
+ bool a;
+ };
+
+ Mask mask;
+
+ static ColorMode disabled() {
+ return ColorMode { Replace(), {}, { false, false, false, false } };
+ }
+
+ static ColorMode unblended() {
+ return ColorMode { Replace(), {}, { true, true, true, true } };
+ }
+
+ static ColorMode alphaBlended() {
+ return ColorMode { Add { One, OneMinusSrcAlpha }, {}, { true, true, true, true } };
+ }
+};
+
+constexpr bool operator!=(const ColorMode::Mask& a, const ColorMode::Mask& b) {
+ return a.r != b.r || a.g != b.g || a.b != b.b || a.a != b.a;
+}
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index 23b28a15df..5048ffcd66 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -3,10 +3,25 @@
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/vertex_array.hpp>
#include <mbgl/util/traits.hpp>
+#include <mbgl/util/std.hpp>
+#include <mbgl/util/logging.hpp>
+
+#include <cstring>
namespace mbgl {
namespace gl {
+static_assert(underlying_type(ShaderType::Vertex) == GL_VERTEX_SHADER, "OpenGL type mismatch");
+static_assert(underlying_type(ShaderType::Fragment) == GL_FRAGMENT_SHADER, "OpenGL type mismatch");
+
+static_assert(underlying_type(PrimitiveType::Points) == GL_POINTS, "OpenGL type mismatch");
+static_assert(underlying_type(PrimitiveType::Lines) == GL_LINES, "OpenGL type mismatch");
+static_assert(underlying_type(PrimitiveType::LineLoop) == GL_LINE_LOOP, "OpenGL type mismatch");
+static_assert(underlying_type(PrimitiveType::LineStrip) == GL_LINE_STRIP, "OpenGL type mismatch");
+static_assert(underlying_type(PrimitiveType::Triangles) == GL_TRIANGLES, "OpenGL type mismatch");
+static_assert(underlying_type(PrimitiveType::TriangleStrip) == GL_TRIANGLE_STRIP, "OpenGL type mismatch");
+static_assert(underlying_type(PrimitiveType::TriangleFan) == GL_TRIANGLE_FAN, "OpenGL type mismatch");
+
static_assert(std::is_same<ProgramID, GLuint>::value, "OpenGL type mismatch");
static_assert(std::is_same<ShaderID, GLuint>::value, "OpenGL type mismatch");
static_assert(std::is_same<BufferID, GLuint>::value, "OpenGL type mismatch");
@@ -15,81 +30,66 @@ static_assert(std::is_same<VertexArrayID, GLuint>::value, "OpenGL type mismatch"
static_assert(std::is_same<FramebufferID, GLuint>::value, "OpenGL type mismatch");
static_assert(std::is_same<RenderbufferID, GLuint>::value, "OpenGL type mismatch");
-static_assert(std::is_same<StencilValue, GLint>::value, "OpenGL type mismatch");
-static_assert(std::is_same<StencilMaskValue, GLuint>::value, "OpenGL type mismatch");
-
-static_assert(underlying_type(StencilTestFunction::Never) == GL_NEVER, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestFunction::Less) == GL_LESS, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestFunction::Equal) == GL_EQUAL, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestFunction::LessEqual) == GL_LEQUAL, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestFunction::Greater) == GL_GREATER, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestFunction::NotEqual) == GL_NOTEQUAL, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestFunction::GreaterEqual) == GL_GEQUAL, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestFunction::Always) == GL_ALWAYS, "OpenGL enum mismatch");
-
-static_assert(underlying_type(StencilTestOperation::Keep) == GL_KEEP, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestOperation::Zero) == GL_ZERO, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestOperation::Replace) == GL_REPLACE, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestOperation::Increment) == GL_INCR, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestOperation::IncrementWrap) == GL_INCR_WRAP, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestOperation::Decrement) == GL_DECR, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestOperation::DecrementWrap) == GL_DECR_WRAP, "OpenGL enum mismatch");
-static_assert(underlying_type(StencilTestOperation::Invert) == GL_INVERT, "OpenGL enum mismatch");
-
-static_assert(underlying_type(DepthTestFunction::Never) == GL_NEVER, "OpenGL enum mismatch");
-static_assert(underlying_type(DepthTestFunction::Less) == GL_LESS, "OpenGL enum mismatch");
-static_assert(underlying_type(DepthTestFunction::Equal) == GL_EQUAL, "OpenGL enum mismatch");
-static_assert(underlying_type(DepthTestFunction::LessEqual) == GL_LEQUAL, "OpenGL enum mismatch");
-static_assert(underlying_type(DepthTestFunction::Greater) == GL_GREATER, "OpenGL enum mismatch");
-static_assert(underlying_type(DepthTestFunction::NotEqual) == GL_NOTEQUAL, "OpenGL enum mismatch");
-static_assert(underlying_type(DepthTestFunction::GreaterEqual) == GL_GEQUAL, "OpenGL enum mismatch");
-static_assert(underlying_type(DepthTestFunction::Always) == GL_ALWAYS, "OpenGL enum mismatch");
-
-static_assert(underlying_type(BlendSourceFactor::Zero) == GL_ZERO, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::One) == GL_ONE, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::SrcColor) == GL_SRC_COLOR, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::OneMinusSrcColor) == GL_ONE_MINUS_SRC_COLOR, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::DstColor) == GL_DST_COLOR, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::OneMinusDstColor) == GL_ONE_MINUS_DST_COLOR, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::SrcAlpha) == GL_SRC_ALPHA, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::OneMinusSrcAlpha) == GL_ONE_MINUS_SRC_ALPHA, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::DstAlpha) == GL_DST_ALPHA, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::OneMinusDstAlpha) == GL_ONE_MINUS_DST_ALPHA, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::ConstantColor) == GL_CONSTANT_COLOR, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::OneMinusConstantColor) == GL_ONE_MINUS_CONSTANT_COLOR, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::ConstantAlpha) == GL_CONSTANT_ALPHA, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::OneMinusConstantAlpha) == GL_ONE_MINUS_CONSTANT_ALPHA, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendSourceFactor::SrcAlphaSaturate) == GL_SRC_ALPHA_SATURATE, "OpenGL enum mismatch");
-
-static_assert(underlying_type(BlendDestinationFactor::Zero) == GL_ZERO, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::One) == GL_ONE, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::SrcColor) == GL_SRC_COLOR, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::OneMinusSrcColor) == GL_ONE_MINUS_SRC_COLOR, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::DstColor) == GL_DST_COLOR, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::OneMinusDstColor) == GL_ONE_MINUS_DST_COLOR, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::SrcAlpha) == GL_SRC_ALPHA, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::OneMinusSrcAlpha) == GL_ONE_MINUS_SRC_ALPHA, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::DstAlpha) == GL_DST_ALPHA, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::OneMinusDstAlpha) == GL_ONE_MINUS_DST_ALPHA, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::ConstantColor) == GL_CONSTANT_COLOR, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::OneMinusConstantColor) == GL_ONE_MINUS_CONSTANT_COLOR, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::ConstantAlpha) == GL_CONSTANT_ALPHA, "OpenGL enum mismatch");
-static_assert(underlying_type(BlendDestinationFactor::OneMinusConstantAlpha) == GL_ONE_MINUS_CONSTANT_ALPHA, "OpenGL enum mismatch");
+static_assert(std::is_same<std::underlying_type_t<TextureFormat>, GLenum>::value, "OpenGL type mismatch");
+static_assert(underlying_type(TextureFormat::RGBA) == GL_RGBA, "OpenGL type mismatch");
+static_assert(underlying_type(TextureFormat::Alpha) == GL_ALPHA, "OpenGL type mismatch");
Context::~Context() {
reset();
}
-UniqueProgram Context::createProgram() {
- return UniqueProgram{ MBGL_CHECK_ERROR(glCreateProgram()), { this } };
+UniqueShader Context::createShader(ShaderType type, const std::string& source) {
+ UniqueShader result { MBGL_CHECK_ERROR(glCreateShader(static_cast<GLenum>(type))), { this } };
+
+ const GLchar* sources = source.data();
+ const GLsizei lengths = static_cast<GLsizei>(source.length());
+ MBGL_CHECK_ERROR(glShaderSource(result, 1, &sources, &lengths));
+ MBGL_CHECK_ERROR(glCompileShader(result));
+
+ GLint status = 0;
+ MBGL_CHECK_ERROR(glGetShaderiv(result, GL_COMPILE_STATUS, &status));
+ if (status != 0) {
+ return result;
+ }
+
+ GLint logLength;
+ MBGL_CHECK_ERROR(glGetShaderiv(result, GL_INFO_LOG_LENGTH, &logLength));
+ if (logLength > 0) {
+ const auto log = std::make_unique<GLchar[]>(logLength);
+ MBGL_CHECK_ERROR(glGetShaderInfoLog(result, logLength, &logLength, log.get()));
+ Log::Error(Event::Shader, "Shader failed to compile: %s", log.get());
+ }
+
+ throw std::runtime_error("shader failed to compile");
}
-UniqueShader Context::createVertexShader() {
- return UniqueShader{ MBGL_CHECK_ERROR(glCreateShader(GL_VERTEX_SHADER)), { this } };
+UniqueProgram Context::createProgram(ShaderID vertexShader, ShaderID fragmentShader) {
+ UniqueProgram result { MBGL_CHECK_ERROR(glCreateProgram()), { this } };
+
+ MBGL_CHECK_ERROR(glAttachShader(result, vertexShader));
+ MBGL_CHECK_ERROR(glAttachShader(result, fragmentShader));
+
+ return result;
}
-UniqueShader Context::createFragmentShader() {
- return UniqueShader{ MBGL_CHECK_ERROR(glCreateShader(GL_FRAGMENT_SHADER)), { this } };
+void Context::linkProgram(ProgramID program_) {
+ MBGL_CHECK_ERROR(glLinkProgram(program_));
+
+ GLint status;
+ MBGL_CHECK_ERROR(glGetProgramiv(program_, GL_LINK_STATUS, &status));
+ if (status == GL_TRUE) {
+ return;
+ }
+
+ GLint logLength;
+ MBGL_CHECK_ERROR(glGetProgramiv(program_, GL_INFO_LOG_LENGTH, &logLength));
+ const auto log = std::make_unique<GLchar[]>(logLength);
+ if (logLength > 0) {
+ MBGL_CHECK_ERROR(glGetProgramInfoLog(program_, logLength, &logLength, log.get()));
+ Log::Error(Event::Shader, "Program failed to link: %s", log.get());
+ }
+
+ throw std::runtime_error("program failed to link");
}
UniqueBuffer Context::createVertexBuffer(const void* data, std::size_t size) {
@@ -105,21 +105,12 @@ UniqueBuffer Context::createIndexBuffer(const void* data, std::size_t size) {
BufferID id = 0;
MBGL_CHECK_ERROR(glGenBuffers(1, &id));
UniqueBuffer result { std::move(id), { this } };
+ vertexArrayObject = 0;
elementBuffer = result;
MBGL_CHECK_ERROR(glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW));
return result;
}
-void Context::bindAttribute(const AttributeBinding& binding, std::size_t stride, const int8_t* offset) {
- MBGL_CHECK_ERROR(glEnableVertexAttribArray(binding.location));
- MBGL_CHECK_ERROR(glVertexAttribPointer(binding.location,
- binding.count,
- static_cast<GLenum>(binding.type),
- false,
- static_cast<GLsizei>(stride),
- offset + binding.offset));
-}
-
UniqueTexture Context::createTexture() {
if (pooledTextures.empty()) {
pooledTextures.resize(TextureMax);
@@ -131,31 +122,60 @@ UniqueTexture Context::createTexture() {
return UniqueTexture{ std::move(id), { this } };
}
-UniqueVertexArray Context::createVertexArray() {
- VertexArrayID id = 0;
- MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &id));
- return UniqueVertexArray{ std::move(id), { this } };
-}
-
UniqueFramebuffer Context::createFramebuffer() {
FramebufferID id = 0;
MBGL_CHECK_ERROR(glGenFramebuffers(1, &id));
return UniqueFramebuffer{ std::move(id), { this } };
}
-UniqueRenderbuffer Context::createRenderbuffer(const RenderbufferType type,
- const uint16_t width,
- const uint16_t height) {
+UniqueRenderbuffer Context::createRenderbuffer(const RenderbufferType type, const Size size) {
RenderbufferID id = 0;
MBGL_CHECK_ERROR(glGenRenderbuffers(1, &id));
UniqueRenderbuffer renderbuffer{ std::move(id), { this } };
bindRenderbuffer = renderbuffer;
MBGL_CHECK_ERROR(
- glRenderbufferStorage(GL_RENDERBUFFER, static_cast<GLenum>(type), width, height));
+ glRenderbufferStorage(GL_RENDERBUFFER, static_cast<GLenum>(type), size.width, size.height));
return renderbuffer;
}
+std::unique_ptr<uint8_t[]> Context::readFramebuffer(const Size size, const TextureFormat format, const bool flip) {
+ const size_t stride = size.width * (format == TextureFormat::RGBA ? 4 : 1);
+ auto data = std::make_unique<uint8_t[]>(stride * size.height);
+
+#if not MBGL_USE_GLES2
+ // When reading data from the framebuffer, make sure that we are storing the values
+ // tightly packed into the buffer to avoid buffer overruns.
+ pixelStorePack = { 1 };
+#endif // MBGL_USE_GLES2
+
+ MBGL_CHECK_ERROR(glReadPixels(0, 0, size.width, size.height, static_cast<GLenum>(format),
+ GL_UNSIGNED_BYTE, data.get()));
+
+ if (flip) {
+ auto tmp = std::make_unique<uint8_t[]>(stride);
+ uint8_t* rgba = data.get();
+ for (int i = 0, j = size.height - 1; i < j; i++, j--) {
+ std::memcpy(tmp.get(), rgba + i * stride, stride);
+ std::memcpy(rgba + i * stride, rgba + j * stride, stride);
+ std::memcpy(rgba + j * stride, tmp.get(), stride);
+ }
+ }
+
+ return data;
+}
+
+#if not MBGL_USE_GLES2
+void Context::drawPixels(const Size size, const void* data, TextureFormat format) {
+ pixelStoreUnpack = { 1 };
+ if (format != TextureFormat::RGBA) {
+ format = static_cast<TextureFormat>(GL_LUMINANCE);
+ }
+ MBGL_CHECK_ERROR(glDrawPixels(size.width, size.height, static_cast<GLenum>(GL_LUMINANCE),
+ GL_UNSIGNED_BYTE, data));
+}
+#endif // MBGL_USE_GLES2
+
namespace {
void checkFramebuffer() {
@@ -251,35 +271,62 @@ Framebuffer Context::createFramebuffer(const Texture& color) {
}
UniqueTexture
-Context::createTexture(uint16_t width, uint16_t height, const void* data, TextureUnit unit) {
+Context::createTexture(const Size size, const void* data, TextureFormat format, TextureUnit unit) {
auto obj = createTexture();
- activeTexture = unit;
- texture[unit] = obj;
+ updateTexture(obj, size, data, format, unit);
+ // We are using clamp to edge here since OpenGL ES doesn't allow GL_REPEAT on NPOT textures.
+ // We use those when the pixelRatio isn't a power of two, e.g. on iPhone 6 Plus.
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
- MBGL_CHECK_ERROR(
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data));
return obj;
}
+void Context::updateTexture(
+ TextureID id, const Size size, const void* data, TextureFormat format, TextureUnit unit) {
+ activeTexture = unit;
+ texture[unit] = id;
+ MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, static_cast<GLenum>(format), size.width,
+ size.height, 0, static_cast<GLenum>(format), GL_UNSIGNED_BYTE,
+ data));
+}
+
void Context::bindTexture(Texture& obj,
TextureUnit unit,
TextureFilter filter,
- TextureMipMap mipmap) {
- if (filter != obj.filter || mipmap != obj.mipmap) {
+ TextureMipMap mipmap,
+ TextureWrap wrapX,
+ TextureWrap wrapY) {
+ if (filter != obj.filter || mipmap != obj.mipmap || wrapX != obj.wrapX || wrapY != obj.wrapY) {
activeTexture = unit;
texture[unit] = obj.texture;
- MBGL_CHECK_ERROR(glTexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- filter == TextureFilter::Linear
- ? (mipmap == TextureMipMap::Yes ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR)
- : (mipmap == TextureMipMap::Yes ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST)));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
- filter == TextureFilter::Linear ? GL_LINEAR : GL_NEAREST));
- obj.filter = filter;
- obj.mipmap = mipmap;
+
+ if (filter != obj.filter || mipmap != obj.mipmap) {
+ MBGL_CHECK_ERROR(glTexParameteri(
+ GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ filter == TextureFilter::Linear
+ ? (mipmap == TextureMipMap::Yes ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR)
+ : (mipmap == TextureMipMap::Yes ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST)));
+ MBGL_CHECK_ERROR(
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ filter == TextureFilter::Linear ? GL_LINEAR : GL_NEAREST));
+ obj.filter = filter;
+ obj.mipmap = mipmap;
+ }
+ if (wrapX != obj.wrapX) {
+
+ MBGL_CHECK_ERROR(
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
+ wrapX == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT));
+ obj.wrapX = wrapX;
+ }
+ if (wrapY != obj.wrapY) {
+ MBGL_CHECK_ERROR(
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
+ wrapY == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT));
+ obj.wrapY = wrapY;
+ }
} else if (texture[unit] != obj.texture) {
// We are checking first to avoid setting the active texture without a subsequent
// texture bind.
@@ -306,6 +353,7 @@ void Context::setDirtyState() {
depthTest.setDirty();
depthFunc.setDirty();
blend.setDirty();
+ blendEquation.setDirty();
blendFunc.setDirty();
blendColor.setDirty();
colorMask.setDirty();
@@ -316,8 +364,13 @@ void Context::setDirtyState() {
lineWidth.setDirty();
activeTexture.setDirty();
#if not MBGL_USE_GLES2
+ pointSize.setDirty();
pixelZoom.setDirty();
rasterPos.setDirty();
+ pixelStorePack.setDirty();
+ pixelStoreUnpack.setDirty();
+ pixelTransferDepth.setDirty();
+ pixelTransferStencil.setDirty();
#endif // MBGL_USE_GLES2
for (auto& tex : texture) {
tex.setDirty();
@@ -327,6 +380,153 @@ void Context::setDirtyState() {
vertexArrayObject.setDirty();
}
+void Context::clear(optional<mbgl::Color> color,
+ optional<float> depth,
+ optional<int32_t> stencil) {
+ GLbitfield mask = 0;
+
+ if (color) {
+ mask |= GL_COLOR_BUFFER_BIT;
+ clearColor = *color;
+ colorMask = { true, true, true, true };
+ }
+
+ if (depth) {
+ mask |= GL_DEPTH_BUFFER_BIT;
+ clearDepth = *depth;
+ depthMask = true;
+ }
+
+ if (stencil) {
+ mask |= GL_STENCIL_BUFFER_BIT;
+ clearStencil = *stencil;
+ stencilMask = 0xFF;
+ }
+
+ MBGL_CHECK_ERROR(glClear(mask));
+}
+
+#if not MBGL_USE_GLES2
+PrimitiveType Context::operator()(const Points& points) {
+ pointSize = points.pointSize;
+ return PrimitiveType::Points;
+}
+#else
+PrimitiveType Context::operator()(const Points&) {
+ return PrimitiveType::Points;
+}
+#endif // MBGL_USE_GLES2
+
+PrimitiveType Context::operator()(const Lines& lines) {
+ lineWidth = lines.lineWidth;
+ return PrimitiveType::Lines;
+}
+
+PrimitiveType Context::operator()(const LineStrip& lineStrip) {
+ lineWidth = lineStrip.lineWidth;
+ return PrimitiveType::LineStrip;
+}
+
+PrimitiveType Context::operator()(const Triangles&) {
+ return PrimitiveType::Triangles;
+}
+
+PrimitiveType Context::operator()(const TriangleStrip&) {
+ return PrimitiveType::TriangleStrip;
+}
+
+void Context::setDepthMode(const DepthMode& depth) {
+ if (depth.func == DepthMode::Always && !depth.mask) {
+ depthTest = false;
+ } else {
+ depthTest = true;
+ depthFunc = depth.func;
+ depthMask = depth.mask;
+ depthRange = depth.range;
+ }
+}
+
+void Context::setStencilMode(const StencilMode& stencil) {
+ if (stencil.test.is<StencilMode::Always>() && !stencil.mask) {
+ stencilTest = false;
+ } else {
+ stencilTest = true;
+ stencilMask = stencil.mask;
+ stencilOp = { stencil.fail, stencil.depthFail, stencil.pass };
+ apply_visitor([&] (const auto& test) {
+ stencilFunc = { test.func, stencil.ref, test.mask };
+ }, stencil.test);
+ }
+}
+
+void Context::setColorMode(const ColorMode& color) {
+ if (color.blendFunction.is<ColorMode::Replace>()) {
+ blend = false;
+ } else {
+ blend = true;
+ blendColor = color.blendColor;
+ apply_visitor([&] (const auto& blendFunction) {
+ blendEquation = ColorMode::BlendEquation(blendFunction.equation);
+ blendFunc = { blendFunction.srcFactor, blendFunction.dstFactor };
+ }, color.blendFunction);
+ }
+
+ colorMask = color.mask;
+}
+
+void Context::draw(const Drawable& drawable) {
+ if (drawable.segments.empty()) {
+ return;
+ }
+
+ PrimitiveType primitiveType = apply_visitor([&] (auto m) { return (*this)(m); }, drawable.drawMode);
+
+ setDepthMode(drawable.depthMode);
+ setStencilMode(drawable.stencilMode);
+ setColorMode(drawable.colorMode);
+
+ program = drawable.program;
+
+ drawable.bindUniforms();
+
+ for (const auto& segment : drawable.segments) {
+ auto needAttributeBindings = [&] () {
+ if (!gl::GenVertexArrays || !gl::BindVertexArray) {
+ return true;
+ }
+
+ if (segment.vao) {
+ vertexArrayObject = *segment.vao;
+ return false;
+ }
+
+ VertexArrayID id = 0;
+ MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &id));
+ vertexArrayObject = id;
+ segment.vao = UniqueVertexArray(std::move(id), { this });
+
+ // If we are initializing a new VAO, we need to force the buffers
+ // to be rebound. VAOs don't inherit the existing buffer bindings.
+ vertexBuffer.setDirty();
+ elementBuffer.setDirty();
+
+ return true;
+ };
+
+ if (needAttributeBindings()) {
+ vertexBuffer = drawable.vertexBuffer;
+ elementBuffer = drawable.indexBuffer;
+ drawable.bindAttributes(segment.vertexOffset);
+ }
+
+ MBGL_CHECK_ERROR(glDrawElements(
+ static_cast<GLenum>(primitiveType),
+ static_cast<GLsizei>(segment.indexLength),
+ GL_UNSIGNED_SHORT,
+ reinterpret_cast<GLvoid*>(sizeof(uint16_t) * segment.indexOffset)));
+ }
+}
+
void Context::performCleanup() {
for (auto id : abandonedPrograms) {
if (program == id) {
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index cf8bb2658b..093afa20ed 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -8,12 +8,21 @@
#include <mbgl/gl/framebuffer.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/gl/index_buffer.hpp>
-#include <mbgl/gl/attribute.hpp>
+#include <mbgl/gl/types.hpp>
+#include <mbgl/gl/draw_mode.hpp>
+#include <mbgl/gl/depth_mode.hpp>
+#include <mbgl/gl/stencil_mode.hpp>
+#include <mbgl/gl/color_mode.hpp>
+#include <mbgl/gl/segment.hpp>
#include <mbgl/util/noncopyable.hpp>
+
+#include <functional>
#include <memory>
#include <vector>
#include <array>
+#include <string>
+#include <unordered_map>
namespace mbgl {
@@ -27,32 +36,31 @@ class Context : private util::noncopyable {
public:
~Context();
- UniqueProgram createProgram();
- UniqueShader createVertexShader();
- UniqueShader createFragmentShader();
+ UniqueShader createShader(ShaderType type, const std::string& source);
+ UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader);
+ void linkProgram(ProgramID);
UniqueTexture createTexture();
- UniqueVertexArray createVertexArray();
- template <class V>
- VertexBuffer<V> createVertexBuffer(std::vector<V>&& v) {
- return VertexBuffer<V> {
- v.size(),
- createVertexBuffer(v.data(), v.size() * sizeof(V))
+ template <class Vertex, class DrawMode>
+ VertexBuffer<Vertex, DrawMode> createVertexBuffer(VertexVector<Vertex, DrawMode>&& v) {
+ return VertexBuffer<Vertex, DrawMode> {
+ v.vertexSize(),
+ createVertexBuffer(v.data(), v.byteSize())
};
}
- template <class P>
- IndexBuffer<P> createIndexBuffer(std::vector<P>&& v) {
- return IndexBuffer<P> {
- createIndexBuffer(v.data(), v.size() * sizeof(P))
+ template <class DrawMode>
+ IndexBuffer<DrawMode> createIndexBuffer(IndexVector<DrawMode>&& v) {
+ return IndexBuffer<DrawMode> {
+ createIndexBuffer(v.data(), v.byteSize())
};
}
template <RenderbufferType type>
- Renderbuffer<type> createRenderbuffer(const std::array<uint16_t, 2>& size) {
+ Renderbuffer<type> createRenderbuffer(const Size size) {
static_assert(type == RenderbufferType::RGBA || type == RenderbufferType::DepthStencil,
"invalid renderbuffer type");
- return { size, createRenderbuffer(type, size[0], size[1]) };
+ return { size, createRenderbuffer(type, size) };
}
Framebuffer createFramebuffer(const Renderbuffer<RenderbufferType::RGBA>&,
@@ -62,30 +70,73 @@ public:
const Renderbuffer<RenderbufferType::DepthStencil>&);
Framebuffer createFramebuffer(const Texture&);
+ template <typename Image,
+ TextureFormat format = Image::channels == 4 ? TextureFormat::RGBA
+ : TextureFormat::Alpha>
+ Image readFramebuffer(const Size size, bool flip = true) {
+ static_assert(Image::channels == (format == TextureFormat::RGBA ? 4 : 1),
+ "image format mismatch");
+ return { size, readFramebuffer(size, format, flip) };
+ }
+
+#if not MBGL_USE_GLES2
+ template <typename Image>
+ void drawPixels(const Image& image) {
+ auto format = image.channels == 4 ? TextureFormat::RGBA : TextureFormat::Alpha;
+ drawPixels(image.size, image.data.get(), format);
+ }
+#endif // MBGL_USE_GLES2
+
// Create a texture from an image with data.
template <typename Image>
Texture createTexture(const Image& image, TextureUnit unit = 0) {
- return { {{ image.width, image.height }},
- createTexture(image.width, image.height, image.data.get(), unit) };
+ auto format = image.channels == 4 ? TextureFormat::RGBA : TextureFormat::Alpha;
+ return { image.size, createTexture(image.size, image.data.get(), format, unit) };
+ }
+
+ template <typename Image>
+ void updateTexture(Texture& obj, const Image& image, TextureUnit unit = 0) {
+ auto format = image.channels == 4 ? TextureFormat::RGBA : TextureFormat::Alpha;
+ updateTexture(obj.texture.get(), image.size, image.data.get(), format, unit);
+ obj.size = image.size;
}
// Creates an empty texture with the specified dimensions.
- Texture createTexture(const std::array<uint16_t, 2>& size, TextureUnit unit = 0) {
- return { size, createTexture(size[0], size[1], nullptr, unit) };
+ Texture createTexture(const Size size,
+ TextureFormat format = TextureFormat::RGBA,
+ TextureUnit unit = 0) {
+ return { size, createTexture(size, nullptr, format, unit) };
}
void bindTexture(Texture&,
TextureUnit = 0,
TextureFilter = TextureFilter::Nearest,
- TextureMipMap = TextureMipMap::No);
-
- template <class Shader, class Vertex>
- void bindAttributes(const Shader& shader, const VertexBuffer<Vertex>&, const int8_t* offset) {
- static_assert(std::is_same<typename Shader::VertexType, Vertex>::value, "vertex type mismatch");
- for (const auto& binding : AttributeBindings<Shader, Vertex>()(shader)) {
- bindAttribute(binding, sizeof(Vertex), offset);
- }
- }
+ TextureMipMap = TextureMipMap::No,
+ TextureWrap wrapX = TextureWrap::Clamp,
+ TextureWrap wrapY = TextureWrap::Clamp);
+
+ void clear(optional<mbgl::Color> color,
+ optional<float> depth,
+ optional<int32_t> stencil);
+
+ struct Drawable {
+ DrawMode drawMode;
+ DepthMode depthMode;
+ StencilMode stencilMode;
+ ColorMode colorMode;
+ gl::ProgramID program;
+ gl::BufferID vertexBuffer;
+ gl::BufferID indexBuffer;
+ const std::vector<Segment>& segments;
+ std::function<void ()> bindUniforms;
+ std::function<void (std::size_t)> bindAttributes;
+ };
+
+ void draw(const Drawable&);
+
+ void setDepthMode(const DepthMode&);
+ void setStencilMode(const StencilMode&);
+ void setColorMode(const ColorMode&);
// Actually remove the objects we marked as abandoned with the above methods.
// Only call this while the OpenGL context is exclusive to this thread.
@@ -107,6 +158,23 @@ public:
void setDirtyState();
+ State<value::ActiveTexture> activeTexture;
+ State<value::BindFramebuffer> bindFramebuffer;
+ State<value::Viewport> viewport;
+ std::array<State<value::BindTexture>, 2> texture;
+ State<value::BindVertexArray> vertexArrayObject;
+ State<value::Program> program;
+
+#if not MBGL_USE_GLES2
+ State<value::PixelZoom> pixelZoom;
+ State<value::RasterPos> rasterPos;
+ State<value::PixelStorePack> pixelStorePack;
+ State<value::PixelStoreUnpack> pixelStoreUnpack;
+ State<value::PixelTransferDepth> pixelTransferDepth;
+ State<value::PixelTransferStencil> pixelTransferStencil;
+#endif // MBGL_USE_GLES2
+
+private:
State<value::StencilFunc> stencilFunc;
State<value::StencilMask> stencilMask;
State<value::StencilTest> stencilTest;
@@ -116,34 +184,37 @@ public:
State<value::DepthTest> depthTest;
State<value::DepthFunc> depthFunc;
State<value::Blend> blend;
+ State<value::BlendEquation> blendEquation;
State<value::BlendFunc> blendFunc;
State<value::BlendColor> blendColor;
State<value::ColorMask> colorMask;
State<value::ClearDepth> clearDepth;
State<value::ClearColor> clearColor;
State<value::ClearStencil> clearStencil;
- State<value::Program> program;
State<value::LineWidth> lineWidth;
- State<value::ActiveTexture> activeTexture;
- State<value::BindFramebuffer> bindFramebuffer;
- State<value::Viewport> viewport;
State<value::BindRenderbuffer> bindRenderbuffer;
#if not MBGL_USE_GLES2
- State<value::PixelZoom> pixelZoom;
- State<value::RasterPos> rasterPos;
+ State<value::PointSize> pointSize;
#endif // MBGL_USE_GLES2
- std::array<State<value::BindTexture>, 2> texture;
State<value::BindVertexBuffer> vertexBuffer;
State<value::BindElementBuffer> elementBuffer;
- State<value::BindVertexArray> vertexArrayObject;
-private:
UniqueBuffer createVertexBuffer(const void* data, std::size_t size);
UniqueBuffer createIndexBuffer(const void* data, std::size_t size);
- UniqueTexture createTexture(uint16_t width, uint16_t height, const void* data, TextureUnit);
+ UniqueTexture createTexture(Size size, const void* data, TextureFormat, TextureUnit);
+ void updateTexture(TextureID, Size size, const void* data, TextureFormat, TextureUnit);
UniqueFramebuffer createFramebuffer();
- UniqueRenderbuffer createRenderbuffer(RenderbufferType, uint16_t width, uint16_t height);
- void bindAttribute(const AttributeBinding&, std::size_t stride, const int8_t* offset);
+ UniqueRenderbuffer createRenderbuffer(RenderbufferType, Size size);
+ std::unique_ptr<uint8_t[]> readFramebuffer(Size, TextureFormat, bool flip);
+#if not MBGL_USE_GLES2
+ void drawPixels(Size size, const void* data, TextureFormat);
+#endif // MBGL_USE_GLES2
+
+ PrimitiveType operator()(const Points&);
+ PrimitiveType operator()(const Lines&);
+ PrimitiveType operator()(const LineStrip&);
+ PrimitiveType operator()(const Triangles&);
+ PrimitiveType operator()(const TriangleStrip&);
friend detail::ProgramDeleter;
friend detail::ShaderDeleter;
diff --git a/src/mbgl/gl/debugging.cpp b/src/mbgl/gl/debugging.cpp
index 1d82b6afb0..8037fc5ef5 100644
--- a/src/mbgl/gl/debugging.cpp
+++ b/src/mbgl/gl/debugging.cpp
@@ -2,8 +2,8 @@
#include <mbgl/gl/debugging.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/extension.hpp>
-#include <mbgl/platform/event.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/event.hpp>
+#include <mbgl/util/logging.hpp>
#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
diff --git a/src/mbgl/gl/depth_mode.cpp b/src/mbgl/gl/depth_mode.cpp
new file mode 100644
index 0000000000..21af75a391
--- /dev/null
+++ b/src/mbgl/gl/depth_mode.cpp
@@ -0,0 +1,18 @@
+#include <mbgl/gl/depth_mode.hpp>
+#include <mbgl/gl/gl.hpp>
+#include <mbgl/util/traits.hpp>
+
+namespace mbgl {
+namespace gl {
+
+static_assert(underlying_type(DepthMode::Never) == GL_NEVER, "OpenGL enum mismatch");
+static_assert(underlying_type(DepthMode::Less) == GL_LESS, "OpenGL enum mismatch");
+static_assert(underlying_type(DepthMode::Equal) == GL_EQUAL, "OpenGL enum mismatch");
+static_assert(underlying_type(DepthMode::LessEqual) == GL_LEQUAL, "OpenGL enum mismatch");
+static_assert(underlying_type(DepthMode::Greater) == GL_GREATER, "OpenGL enum mismatch");
+static_assert(underlying_type(DepthMode::NotEqual) == GL_NOTEQUAL, "OpenGL enum mismatch");
+static_assert(underlying_type(DepthMode::GreaterEqual) == GL_GEQUAL, "OpenGL enum mismatch");
+static_assert(underlying_type(DepthMode::Always) == GL_ALWAYS, "OpenGL enum mismatch");
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/depth_mode.hpp b/src/mbgl/gl/depth_mode.hpp
new file mode 100644
index 0000000000..37617e3c34
--- /dev/null
+++ b/src/mbgl/gl/depth_mode.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <mbgl/util/range.hpp>
+
+namespace mbgl {
+namespace gl {
+
+class DepthMode {
+public:
+ enum Function {
+ Never = 0x0200,
+ Less = 0x0201,
+ Equal = 0x0202,
+ LessEqual = 0x0203,
+ Greater = 0x0204,
+ NotEqual = 0x0205,
+ GreaterEqual = 0x0206,
+ Always = 0x0207
+ };
+
+ enum Mask : bool {
+ ReadOnly = false,
+ ReadWrite = true
+ };
+
+ Function func;
+ Mask mask;
+ Range<float> range;
+
+ static DepthMode disabled() {
+ return DepthMode { Always, ReadOnly, { 0.0, 1.0 } };
+ }
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/draw_mode.hpp b/src/mbgl/gl/draw_mode.hpp
new file mode 100644
index 0000000000..ab86d5e469
--- /dev/null
+++ b/src/mbgl/gl/draw_mode.hpp
@@ -0,0 +1,76 @@
+#pragma once
+
+#include <mbgl/gl/primitives.hpp>
+#include <mbgl/util/variant.hpp>
+
+#include <cassert>
+
+namespace mbgl {
+namespace gl {
+
+class Points {
+public:
+ using Primitive = Point;
+ static constexpr std::size_t bufferGroupSize = 1;
+
+ explicit Points(float pointSize_) : pointSize(pointSize_) {}
+
+ float pointSize;
+};
+
+class Lines {
+public:
+ using Primitive = Line;
+ static constexpr std::size_t bufferGroupSize = 2;
+
+ explicit Lines(float lineWidth_) : lineWidth(lineWidth_) {
+ assert(lineWidth > 0);
+ }
+
+ float lineWidth;
+};
+
+class LineStrip {
+public:
+ // LineStrip is a form of "Line" rendering, but the element buffer
+ // cannot be grouped into logical elements beyond a single Point.
+ using Primitive = Line;
+ static constexpr std::size_t bufferGroupSize = 1;
+
+ explicit LineStrip(float lineWidth_) : lineWidth(lineWidth_) {
+ assert(lineWidth > 0);
+ }
+
+ float lineWidth;
+};
+
+class Triangles {
+public:
+ using Primitive = Triangle;
+ static constexpr std::size_t bufferGroupSize = 3;
+};
+
+class TriangleStrip {
+public:
+ // TriangleStrip is a form of "Triangle" rendering, but the element buffer
+ // cannot be grouped into logical elements beyond a single Point.
+ using Primitive = Triangle;
+ static constexpr std::size_t bufferGroupSize = 1;
+};
+
+// Special draw mode for use with VertexVector<Indexed, Vertex>, in which
+// case the true draw mode is denoted by the IndexVector type.
+class Indexed {
+public:
+ static constexpr std::size_t bufferGroupSize = 1;
+};
+
+using DrawMode = variant<
+ Points,
+ Lines,
+ LineStrip,
+ Triangles,
+ TriangleStrip>;
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/extension.cpp b/src/mbgl/gl/extension.cpp
index ee94e8ecfd..e6b4d9156e 100644
--- a/src/mbgl/gl/extension.cpp
+++ b/src/mbgl/gl/extension.cpp
@@ -4,6 +4,7 @@
#include <mutex>
#include <string>
#include <vector>
+#include <cstring>
namespace mbgl {
namespace gl {
@@ -26,18 +27,14 @@ static std::once_flag initializeExtensionsOnce;
void InitializeExtensions(glProc (*getProcAddress)(const char*)) {
std::call_once(initializeExtensionsOnce, [getProcAddress] {
- const char* extensionsPtr =
- reinterpret_cast<const char*>(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)));
-
- if (!extensionsPtr)
- return;
-
- const std::string extensions = extensionsPtr;
- for (auto fn : detail::extensionFunctions()) {
- for (auto probe : fn.second) {
- if (extensions.find(probe.first) != std::string::npos) {
- *fn.first = getProcAddress(probe.second);
- break;
+ if (const char* extensions =
+ reinterpret_cast<const char*>(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)))) {
+ for (auto fn : detail::extensionFunctions()) {
+ for (auto probe : fn.second) {
+ if (strstr(extensions, probe.first) != nullptr) {
+ *fn.first = getProcAddress(probe.second);
+ break;
+ }
}
}
}
diff --git a/src/mbgl/gl/framebuffer.hpp b/src/mbgl/gl/framebuffer.hpp
index 880fed159e..91ed467b40 100644
--- a/src/mbgl/gl/framebuffer.hpp
+++ b/src/mbgl/gl/framebuffer.hpp
@@ -1,15 +1,14 @@
#pragma once
#include <mbgl/gl/object.hpp>
-
-#include <array>
+#include <mbgl/util/size.hpp>
namespace mbgl {
namespace gl {
class Framebuffer {
public:
- std::array<uint16_t, 2> size;
+ Size size;
gl::UniqueFramebuffer framebuffer;
};
diff --git a/src/mbgl/gl/index_buffer.hpp b/src/mbgl/gl/index_buffer.hpp
index f38d7fd4f5..b3610f4154 100644
--- a/src/mbgl/gl/index_buffer.hpp
+++ b/src/mbgl/gl/index_buffer.hpp
@@ -1,39 +1,38 @@
#pragma once
#include <mbgl/gl/object.hpp>
+#include <mbgl/gl/draw_mode.hpp>
+#include <mbgl/util/ignore.hpp>
+
+#include <vector>
namespace mbgl {
namespace gl {
-class Line {
+template <class DrawMode>
+class IndexVector {
public:
- Line(uint16_t a_, uint16_t b_)
- : a(a_), b(b_) {}
-
- uint16_t a;
- uint16_t b;
+ static constexpr std::size_t groupSize = DrawMode::bufferGroupSize;
- static constexpr std::size_t IndexCount = 2;
-};
+ template <class... Args>
+ void emplace_back(Args&&... args) {
+ static_assert(sizeof...(args) == groupSize, "wrong buffer element count");
+ util::ignore({(v.emplace_back(std::forward<Args>(args)), 0)...});
+ }
-class Triangle {
-public:
- Triangle(uint16_t a_, uint16_t b_, uint16_t c_)
- : a(a_), b(b_), c(c_) {}
+ std::size_t indexSize() const { return v.size(); }
+ std::size_t byteSize() const { return v.size() * sizeof(uint16_t); }
- uint16_t a;
- uint16_t b;
- uint16_t c;
+ bool empty() const { return v.empty(); }
+ const uint16_t* data() const { return v.data(); }
- static constexpr std::size_t IndexCount = 3;
+private:
+ std::vector<uint16_t> v;
};
-template <class Primitive>
+template <class DrawMode>
class IndexBuffer {
public:
- static_assert(std::is_same<Primitive, Line>::value || std::is_same<Primitive, Triangle>::value,
- "primitive must be Line or Triangle");
- static constexpr std::size_t primitiveSize = sizeof(Primitive);
UniqueBuffer buffer;
};
diff --git a/src/mbgl/gl/primitives.hpp b/src/mbgl/gl/primitives.hpp
new file mode 100644
index 0000000000..fe6b1b2e5b
--- /dev/null
+++ b/src/mbgl/gl/primitives.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+namespace mbgl {
+namespace gl {
+
+class Point {
+public:
+ static constexpr std::size_t vertexCount = 1;
+};
+
+class Line {
+public:
+ static constexpr std::size_t vertexCount = 2;
+};
+
+class Triangle {
+public:
+ static constexpr std::size_t vertexCount = 3;
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp
new file mode 100644
index 0000000000..33387e9d4e
--- /dev/null
+++ b/src/mbgl/gl/program.hpp
@@ -0,0 +1,70 @@
+#pragma once
+
+#include <mbgl/gl/types.hpp>
+#include <mbgl/gl/object.hpp>
+#include <mbgl/gl/context.hpp>
+#include <mbgl/gl/vertex_buffer.hpp>
+#include <mbgl/gl/index_buffer.hpp>
+#include <mbgl/gl/attribute.hpp>
+#include <mbgl/gl/uniform.hpp>
+
+#include <string>
+
+namespace mbgl {
+namespace gl {
+
+template <class P, class As, class Us>
+class Program {
+public:
+ using Primitive = P;
+ using Attributes = As;
+ using Uniforms = Us;
+
+ using Vertex = typename Attributes::Vertex;
+ using UniformValues = typename Uniforms::Values;
+
+ static_assert(std::is_standard_layout<Vertex>::value, "vertex type must use standard layout");
+
+ Program(Context& context, const std::string& vertexSource, const std::string& fragmentSource)
+ : vertexShader(context.createShader(ShaderType::Vertex, vertexSource)),
+ fragmentShader(context.createShader(ShaderType::Fragment, fragmentSource)),
+ program(context.createProgram(vertexShader, fragmentShader)),
+ attributesState(Attributes::state(program)),
+ uniformsState((context.linkProgram(program), Uniforms::state(program))) {}
+
+ template <class DrawMode>
+ void draw(Context& context,
+ DrawMode drawMode,
+ DepthMode depthMode,
+ StencilMode stencilMode,
+ ColorMode colorMode,
+ UniformValues&& uniformValues,
+ const VertexBuffer<Vertex>& vertexBuffer,
+ const IndexBuffer<DrawMode>& indexBuffer,
+ const SegmentVector<Attributes>& segments) {
+ static_assert(std::is_same<Primitive, typename DrawMode::Primitive>::value, "incompatible draw mode");
+ context.draw({
+ std::move(drawMode),
+ std::move(depthMode),
+ std::move(stencilMode),
+ std::move(colorMode),
+ program,
+ vertexBuffer.buffer,
+ indexBuffer.buffer,
+ segments,
+ Uniforms::binder(uniformsState, std::move(uniformValues)),
+ Attributes::binder(attributesState)
+ });
+ }
+
+private:
+ UniqueShader vertexShader;
+ UniqueShader fragmentShader;
+ UniqueProgram program;
+
+ typename Attributes::State attributesState;
+ typename Uniforms::State uniformsState;
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/renderbuffer.hpp b/src/mbgl/gl/renderbuffer.hpp
index 9e8993bb77..cc8ff13268 100644
--- a/src/mbgl/gl/renderbuffer.hpp
+++ b/src/mbgl/gl/renderbuffer.hpp
@@ -1,8 +1,7 @@
#pragma once
#include <mbgl/gl/object.hpp>
-
-#include <array>
+#include <mbgl/util/size.hpp>
namespace mbgl {
namespace gl {
@@ -11,7 +10,7 @@ template <RenderbufferType renderbufferType>
class Renderbuffer {
public:
using type = std::integral_constant<RenderbufferType, renderbufferType>;
- std::array<uint16_t, 2> size;
+ Size size;
gl::UniqueRenderbuffer renderbuffer;
};
diff --git a/src/mbgl/gl/segment.hpp b/src/mbgl/gl/segment.hpp
new file mode 100644
index 0000000000..8f74afd237
--- /dev/null
+++ b/src/mbgl/gl/segment.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <mbgl/util/optional.hpp>
+
+#include <cstddef>
+
+namespace mbgl {
+namespace gl {
+
+class Segment {
+public:
+ Segment(std::size_t vertexOffset_,
+ std::size_t indexOffset_,
+ std::size_t vertexLength_ = 0,
+ std::size_t indexLength_ = 0)
+ : vertexOffset(vertexOffset_),
+ indexOffset(indexOffset_),
+ vertexLength(vertexLength_),
+ indexLength(indexLength_) {}
+
+ const std::size_t vertexOffset;
+ const std::size_t indexOffset;
+
+ std::size_t vertexLength;
+ std::size_t indexLength;
+
+private:
+ friend class Context;
+ mutable optional<UniqueVertexArray> vao;
+};
+
+template <class Attributes>
+class SegmentVector : public std::vector<Segment> {
+public:
+ SegmentVector() = default;
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/shader.cpp b/src/mbgl/gl/shader.cpp
deleted file mode 100644
index d8ee734567..0000000000
--- a/src/mbgl/gl/shader.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/gl.hpp>
-#include <mbgl/gl/context.hpp>
-#include <mbgl/util/stopwatch.hpp>
-#include <mbgl/util/exception.hpp>
-#include <mbgl/platform/log.hpp>
-#include <mbgl/platform/platform.hpp>
-
-#include <cstring>
-#include <cassert>
-#include <iostream>
-#include <string>
-#include <fstream>
-#include <cstdio>
-#include <cassert>
-
-namespace mbgl {
-namespace gl {
-
-Shader::Shader(const char* name_,
- const char* vertexSource,
- const char* fragmentSource,
- Context& context,
- Defines defines)
- : name(name_),
- program(context.createProgram()),
- vertexShader(context.createVertexShader()),
- fragmentShader(context.createFragmentShader()) {
- util::stopwatch stopwatch("shader compilation", Event::Shader);
-
- if (!compileShader(vertexShader, vertexSource)) {
- Log::Error(Event::Shader, "Vertex shader %s failed to compile: %s", name, vertexSource);
- throw util::ShaderException(std::string { "Vertex shader " } + name + " failed to compile");
- }
-
- std::string fragment(fragmentSource);
- if (defines & Defines::Overdraw) {
- assert(fragment.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos);
- fragment.replace(fragment.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n");
- }
-
- if (!compileShader(fragmentShader, fragment.c_str())) {
- Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragmentSource);
- throw util::ShaderException(std::string { "Fragment shader " } + name + " failed to compile");
- }
-
- // Attach shaders
- MBGL_CHECK_ERROR(glAttachShader(program.get(), vertexShader.get()));
- MBGL_CHECK_ERROR(glAttachShader(program.get(), fragmentShader.get()));
-
- // Link program
- GLint status;
- MBGL_CHECK_ERROR(glLinkProgram(program.get()));
-
- MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_LINK_STATUS, &status));
- if (status == 0) {
- GLint logLength;
- MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_INFO_LOG_LENGTH, &logLength));
- const auto log = std::make_unique<GLchar[]>(logLength);
- if (logLength > 0) {
- MBGL_CHECK_ERROR(glGetProgramInfoLog(program.get(), logLength, &logLength, log.get()));
- Log::Error(Event::Shader, "Program failed to link: %s", log.get());
- }
- throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get());
- }
-}
-
-bool Shader::compileShader(UniqueShader& shader, const GLchar *source) {
- GLint status = 0;
-
- const GLsizei lengths = static_cast<GLsizei>(std::strlen(source));
- MBGL_CHECK_ERROR(glShaderSource(shader.get(), 1, &source, &lengths));
-
- MBGL_CHECK_ERROR(glCompileShader(shader.get()));
-
- MBGL_CHECK_ERROR(glGetShaderiv(shader.get(), GL_COMPILE_STATUS, &status));
- if (status == 0) {
- GLint logLength;
- MBGL_CHECK_ERROR(glGetShaderiv(shader.get(), GL_INFO_LOG_LENGTH, &logLength));
- if (logLength > 0) {
- const auto log = std::make_unique<GLchar[]>(logLength);
- MBGL_CHECK_ERROR(glGetShaderInfoLog(shader.get(), logLength, &logLength, log.get()));
- Log::Error(Event::Shader, "Shader failed to compile: %s", log.get());
- }
- return false;
- }
-
- MBGL_CHECK_ERROR(glGetShaderiv(shader.get(), GL_COMPILE_STATUS, &status));
- if (status == GL_FALSE) {
- Log::Error(Event::Shader, "Shader %s failed to compile.", name);
- return false;
- }
-
- return true;
-}
-
-Shader::~Shader() {
- if (program.get()) {
- MBGL_CHECK_ERROR(glDetachShader(program.get(), vertexShader.get()));
- MBGL_CHECK_ERROR(glDetachShader(program.get(), fragmentShader.get()));
- }
-}
-
-UniformLocation Shader::getUniformLocation(const char* uniform) const {
- return MBGL_CHECK_ERROR(glGetUniformLocation(program.get(), uniform));
-}
-
-AttributeLocation Shader::getAttributeLocation(const char* attribute) const {
- return MBGL_CHECK_ERROR(glGetAttribLocation(program.get(), attribute));
-}
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/gl/shader.hpp b/src/mbgl/gl/shader.hpp
deleted file mode 100644
index f88bd4f867..0000000000
--- a/src/mbgl/gl/shader.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/types.hpp>
-#include <mbgl/gl/object.hpp>
-#include <mbgl/util/noncopyable.hpp>
-
-namespace mbgl {
-namespace gl {
-
-class Context;
-
-class Shader : private util::noncopyable {
-public:
- ~Shader();
- const char* name;
-
- ProgramID getID() const {
- return program.get();
- }
-
- AttributeLocation getAttributeLocation(const char* uniform) const;
- UniformLocation getUniformLocation(const char* uniform) const;
-
- enum Defines : bool {
- None = false,
- Overdraw = true,
- };
-
-protected:
- Shader(const char* name_,
- const char* vertex,
- const char* fragment,
- Context&,
- Defines defines = Defines::None);
-
-private:
- bool compileShader(UniqueShader&, const char *source);
-
- UniqueProgram program;
- UniqueShader vertexShader;
- UniqueShader fragmentShader;
-};
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/gl/stencil_mode.cpp b/src/mbgl/gl/stencil_mode.cpp
new file mode 100644
index 0000000000..6858d6d106
--- /dev/null
+++ b/src/mbgl/gl/stencil_mode.cpp
@@ -0,0 +1,27 @@
+#include <mbgl/gl/stencil_mode.hpp>
+#include <mbgl/gl/gl.hpp>
+#include <mbgl/util/traits.hpp>
+
+namespace mbgl {
+namespace gl {
+
+static_assert(StencilMode::Never::func == GL_NEVER, "OpenGL enum mismatch");
+static_assert(StencilMode::Less::func == GL_LESS, "OpenGL enum mismatch");
+static_assert(StencilMode::Equal::func == GL_EQUAL, "OpenGL enum mismatch");
+static_assert(StencilMode::LessEqual::func == GL_LEQUAL, "OpenGL enum mismatch");
+static_assert(StencilMode::Greater::func == GL_GREATER, "OpenGL enum mismatch");
+static_assert(StencilMode::NotEqual::func == GL_NOTEQUAL, "OpenGL enum mismatch");
+static_assert(StencilMode::GreaterEqual::func == GL_GEQUAL, "OpenGL enum mismatch");
+static_assert(StencilMode::Always::func == GL_ALWAYS, "OpenGL enum mismatch");
+
+static_assert(underlying_type(StencilMode::Keep) == GL_KEEP, "OpenGL enum mismatch");
+static_assert(underlying_type(StencilMode::Zero) == GL_ZERO, "OpenGL enum mismatch");
+static_assert(underlying_type(StencilMode::Replace) == GL_REPLACE, "OpenGL enum mismatch");
+static_assert(underlying_type(StencilMode::Increment) == GL_INCR, "OpenGL enum mismatch");
+static_assert(underlying_type(StencilMode::IncrementWrap) == GL_INCR_WRAP, "OpenGL enum mismatch");
+static_assert(underlying_type(StencilMode::Decrement) == GL_DECR, "OpenGL enum mismatch");
+static_assert(underlying_type(StencilMode::DecrementWrap) == GL_DECR_WRAP, "OpenGL enum mismatch");
+static_assert(underlying_type(StencilMode::Invert) == GL_INVERT, "OpenGL enum mismatch");
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/stencil_mode.hpp b/src/mbgl/gl/stencil_mode.hpp
new file mode 100644
index 0000000000..bc959c9a73
--- /dev/null
+++ b/src/mbgl/gl/stencil_mode.hpp
@@ -0,0 +1,66 @@
+#pragma once
+
+#include <mbgl/util/variant.hpp>
+
+namespace mbgl {
+namespace gl {
+
+class StencilMode {
+public:
+ template <uint32_t F>
+ struct SimpleTest {
+ static constexpr uint32_t func = F;
+ static constexpr uint32_t mask = 0;
+ };
+
+ template <uint32_t F>
+ struct MaskedTest {
+ static constexpr uint32_t func = F;
+ uint32_t mask;
+ };
+
+ using Never = SimpleTest<0x0200>;
+ using Less = MaskedTest<0x0201>;
+ using Equal = MaskedTest<0x0202>;
+ using LessEqual = MaskedTest<0x0203>;
+ using Greater = MaskedTest<0x0204>;
+ using NotEqual = MaskedTest<0x0205>;
+ using GreaterEqual = MaskedTest<0x0206>;
+ using Always = SimpleTest<0x0207>;
+
+ using Test = variant<
+ Never,
+ Less,
+ Equal,
+ LessEqual,
+ Greater,
+ NotEqual,
+ GreaterEqual,
+ Always>;
+
+ enum Op {
+ Zero = 0x0000,
+ Keep = 0x1E00,
+ Replace = 0x1E01,
+ Increment = 0x1E02,
+ Decrement = 0x1E03,
+ Invert = 0x150A,
+ IncrementWrap = 0x8507,
+ DecrementWrap = 0x8508
+ };
+
+ Test test;
+ int32_t ref;
+ uint32_t mask;
+
+ Op fail;
+ Op depthFail;
+ Op pass;
+
+ static StencilMode disabled() {
+ return StencilMode { Always(), 0, 0, Keep, Keep, Keep };
+ }
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/texture.hpp b/src/mbgl/gl/texture.hpp
index 49e1323095..5330689ac2 100644
--- a/src/mbgl/gl/texture.hpp
+++ b/src/mbgl/gl/texture.hpp
@@ -1,18 +1,19 @@
#pragma once
#include <mbgl/gl/object.hpp>
-
-#include <array>
+#include <mbgl/util/size.hpp>
namespace mbgl {
namespace gl {
class Texture {
public:
- std::array<uint16_t, 2> size;
+ Size size;
UniqueTexture texture;
TextureFilter filter = TextureFilter::Nearest;
TextureMipMap mipmap = TextureMipMap::No;
+ TextureWrap wrapX = TextureWrap::Clamp;
+ TextureWrap wrapY = TextureWrap::Clamp;
};
} // namespace gl
diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp
index dccc61b03a..577629d5d3 100644
--- a/src/mbgl/gl/types.hpp
+++ b/src/mbgl/gl/types.hpp
@@ -19,9 +19,10 @@ using AttributeLocation = int32_t;
using UniformLocation = int32_t;
using TextureUnit = uint8_t;
-using DepthValue = double;
-using StencilValue = int32_t;
-using StencilMaskValue = uint32_t;
+enum class ShaderType : uint32_t {
+ Vertex = 0x8B31,
+ Fragment = 0x8B30
+};
enum class DataType : uint32_t {
Byte = 0x1400,
@@ -43,11 +44,6 @@ template <> struct DataTypeOf<int32_t> : std::integral_constant<DataType, DataT
template <> struct DataTypeOf<uint32_t> : std::integral_constant<DataType, DataType::UnsignedInteger> {};
template <> struct DataTypeOf<float> : std::integral_constant<DataType, DataType::Float> {};
-enum class BufferType : uint32_t {
- Vertex = 0x8892,
- Element = 0x8893
-};
-
enum class RenderbufferType : uint32_t {
RGBA = 0x8058,
DepthStencil = 0x88F0,
@@ -55,74 +51,37 @@ enum class RenderbufferType : uint32_t {
enum class TextureMipMap : bool { No = false, Yes = true };
enum class TextureFilter : bool { Nearest = false, Linear = true };
-
-enum class StencilTestFunction : uint32_t {
- Never = 0x0200,
- Less = 0x0201,
- Equal = 0x0202,
- LessEqual = 0x0203,
- Greater = 0x0204,
- NotEqual = 0x0205,
- GreaterEqual = 0x0206,
- Always = 0x0207,
+enum class TextureWrap : bool { Clamp, Repeat };
+enum class TextureFormat : uint32_t {
+ RGBA = 0x1908,
+ Alpha = 0x1906,
+#if not MBGL_USE_GLES2
+ Stencil = 0x1901,
+ Depth = 0x1902,
+#endif // MBGL_USE_GLES2
};
-enum class StencilTestOperation : uint32_t {
- Keep = 0x1E00,
- Zero = 0x0000,
- Replace = 0x1E01,
- Increment = 0x1E02,
- IncrementWrap = 0x8507,
- Decrement = 0x1E03,
- DecrementWrap = 0x8508,
- Invert = 0x150A,
+enum class PrimitiveType {
+ Points = 0x0000,
+ Lines = 0x0001,
+ LineLoop = 0x0002,
+ LineStrip = 0x0003,
+ Triangles = 0x0004,
+ TriangleStrip = 0x0005,
+ TriangleFan = 0x0006
};
-enum class DepthTestFunction : uint32_t {
- Never = 0x0200,
- Less = 0x0201,
- Equal = 0x0202,
- LessEqual = 0x0203,
- Greater = 0x0204,
- NotEqual = 0x0205,
- GreaterEqual = 0x0206,
- Always = 0x0207,
-};
+#if not MBGL_USE_GLES2
-enum class BlendSourceFactor : uint32_t {
- Zero = 0x0000,
- One = 0x0001,
- SrcColor = 0x0300,
- OneMinusSrcColor = 0x0301,
- DstColor = 0x0306,
- OneMinusDstColor = 0x0307,
- SrcAlpha = 0x0302,
- OneMinusSrcAlpha = 0x0303,
- DstAlpha = 0x0304,
- OneMinusDstAlpha = 0x0305,
- ConstantColor = 0x8001,
- OneMinusConstantColor = 0x8002,
- ConstantAlpha = 0x8003,
- OneMinusConstantAlpha = 0x8004,
- SrcAlphaSaturate = 0x0308,
+struct PixelStorageType {
+ int32_t alignment;
};
-enum class BlendDestinationFactor : uint32_t {
- Zero = 0x0000,
- One = 0x0001,
- SrcColor = 0x0300,
- OneMinusSrcColor = 0x0301,
- DstColor = 0x0306,
- OneMinusDstColor = 0x0307,
- SrcAlpha = 0x0302,
- OneMinusSrcAlpha = 0x0303,
- DstAlpha = 0x0304,
- OneMinusDstAlpha = 0x0305,
- ConstantColor = 0x8001,
- OneMinusConstantColor = 0x8002,
- ConstantAlpha = 0x8003,
- OneMinusConstantAlpha = 0x8004,
-};
+constexpr bool operator!=(const PixelStorageType& a, const PixelStorageType& b) {
+ return a.alignment != b.alignment;
+}
+
+#endif // MBGL_USE_GLES2
} // namespace gl
} // namespace mbgl
diff --git a/src/mbgl/gl/uniform.cpp b/src/mbgl/gl/uniform.cpp
index 07a27963d9..7b674f2cde 100644
--- a/src/mbgl/gl/uniform.cpp
+++ b/src/mbgl/gl/uniform.cpp
@@ -1,54 +1,80 @@
#include <mbgl/gl/uniform.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/util/color.hpp>
+#include <mbgl/util/size.hpp>
+#include <mbgl/util/convert.hpp>
namespace mbgl {
namespace gl {
+UniformLocation uniformLocation(ProgramID id, const char* name) {
+ return MBGL_CHECK_ERROR(glGetUniformLocation(id, name));
+}
+
template <>
-void Uniform<float>::bind(const float& t) {
+void bindUniform<float>(UniformLocation location, const float& t) {
MBGL_CHECK_ERROR(glUniform1f(location, t));
}
template <>
-void Uniform<int32_t>::bind(const int32_t& t) {
+void bindUniform<int32_t>(UniformLocation location, const int32_t& t) {
MBGL_CHECK_ERROR(glUniform1i(location, t));
}
template <>
-void Uniform<std::array<float, 2>>::bind(const std::array<float, 2>& t) {
+void bindUniform<std::array<float, 2>>(UniformLocation location, const std::array<float, 2>& t) {
MBGL_CHECK_ERROR(glUniform2fv(location, 1, t.data()));
}
template <>
-void Uniform<std::array<float, 3>>::bind(const std::array<float, 3>& t) {
+void bindUniform<std::array<float, 3>>(UniformLocation location, const std::array<float, 3>& t) {
MBGL_CHECK_ERROR(glUniform3fv(location, 1, t.data()));
}
template <>
-void Uniform<std::array<float, 4>>::bind(const std::array<float, 4>& t) {
+void bindUniform<std::array<float, 4>>(UniformLocation location, const std::array<float, 4>& t) {
MBGL_CHECK_ERROR(glUniform4fv(location, 1, t.data()));
}
template <>
-void Uniform<Color>::bind(const Color& t) {
- std::array<float, 4> a = {{ t.r, t.g, t.b, t.a }};
- MBGL_CHECK_ERROR(glUniform4fv(location, 1, a.data()));
+void bindUniform<std::array<double, 4>>(UniformLocation location, const std::array<double, 4>& t) {
+ MBGL_CHECK_ERROR(glUniformMatrix2fv(location, 1, GL_FALSE, util::convert<float>(t).data()));
+}
+
+template <>
+void bindUniform<std::array<double, 9>>(UniformLocation location, const std::array<double, 9>& t) {
+ MBGL_CHECK_ERROR(glUniformMatrix3fv(location, 1, GL_FALSE, util::convert<float>(t).data()));
+}
+
+template <>
+void bindUniform<std::array<double, 16>>(UniformLocation location, const std::array<double, 16>& t) {
+ MBGL_CHECK_ERROR(glUniformMatrix4fv(location, 1, GL_FALSE, util::convert<float>(t).data()));
+}
+
+
+template <>
+void bindUniform<bool>(UniformLocation location, const bool& t) {
+ return bindUniform(location, int32_t(t));
+}
+
+template <>
+void bindUniform<uint8_t>(UniformLocation location, const uint8_t& t) {
+ bindUniform(location, int32_t(t));
}
template <>
-void UniformMatrix<2>::bind(const std::array<float, 4>& t) {
- MBGL_CHECK_ERROR(glUniformMatrix2fv(location, 1, GL_FALSE, t.data()));
+void bindUniform<Color>(UniformLocation location, const Color& t) {
+ bindUniform(location, std::array<float, 4> {{ t.r, t.g, t.b, t.a }});
}
template <>
-void UniformMatrix<3>::bind(const std::array<float, 9>& t) {
- MBGL_CHECK_ERROR(glUniformMatrix3fv(location, 1, GL_FALSE, t.data()));
+void bindUniform<Size>(UniformLocation location, const Size& t) {
+ bindUniform(location, util::convert<float>(std::array<uint32_t, 2> {{ t.width, t.height }}));
}
template <>
-void UniformMatrix<4>::bind(const std::array<float, 16>& t) {
- MBGL_CHECK_ERROR(glUniformMatrix4fv(location, 1, GL_FALSE, t.data()));
+void bindUniform<std::array<uint16_t, 2>>(UniformLocation location, const std::array<uint16_t, 2>& t) {
+ bindUniform(location, util::convert<float>(t));
}
// Add more as needed.
diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp
index 5af781043d..726cd4fe10 100644
--- a/src/mbgl/gl/uniform.hpp
+++ b/src/mbgl/gl/uniform.hpp
@@ -1,60 +1,80 @@
#pragma once
-#include <mbgl/gl/shader.hpp>
+#include <mbgl/gl/types.hpp>
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/ignore.hpp>
+#include <mbgl/util/indexed_tuple.hpp>
#include <array>
+#include <functional>
namespace mbgl {
namespace gl {
-template <typename T>
+template <class T>
+void bindUniform(UniformLocation, const T&);
+
+template <class Tag, class T>
+class UniformValue {
+public:
+ explicit UniformValue(T t_) : t(std::move(t_)) {}
+ T t;
+};
+
+template <class Tag, class T>
class Uniform {
public:
- Uniform(const char* name, const Shader& shader)
- : current(), location(shader.getUniformLocation(name)) {
- }
+ using Value = UniformValue<Tag, T>;
- void operator=(const T& t) {
- if (current != t) {
- current = t;
- bind(t);
+ class State {
+ public:
+ void operator=(const Value& value) {
+ if (!current || *current != value.t) {
+ current = value.t;
+ bindUniform(location, value.t);
+ }
}
- }
-
-private:
- void bind(const T&);
- T current;
- UniformLocation location;
+ UniformLocation location;
+ optional<T> current = {};
+ };
};
-template <size_t C, size_t R = C>
-class UniformMatrix {
+template <class Tag, class T>
+using UniformScalar = Uniform<Tag, T>;
+
+template <class Tag, class T, size_t N>
+using UniformVector = Uniform<Tag, std::array<T, N>>;
+
+template <class Tag, class T, size_t N>
+using UniformMatrix = Uniform<Tag, std::array<T, N*N>>;
+
+#define MBGL_DEFINE_UNIFORM_SCALAR(type_, name_) \
+ struct name_ : ::mbgl::gl::UniformScalar<name_, type_> { static constexpr auto name = #name_; }
+
+#define MBGL_DEFINE_UNIFORM_VECTOR(type_, n_, name_) \
+ struct name_ : ::mbgl::gl::UniformVector<name_, type_, n_> { static constexpr auto name = #name_; }
+
+#define MBGL_DEFINE_UNIFORM_MATRIX(type_, n_, name_) \
+ struct name_ : ::mbgl::gl::UniformMatrix<name_, type_, n_> { static constexpr auto name = #name_; }
+
+UniformLocation uniformLocation(ProgramID, const char * name);
+
+template <class... Us>
+class Uniforms {
public:
- typedef std::array<float, C*R> T;
+ using State = IndexedTuple<TypeList<Us...>, TypeList<typename Us::State...>>;
+ using Values = IndexedTuple<TypeList<Us...>, TypeList<typename Us::Value...>>;
- UniformMatrix(const char* name, const Shader& shader)
- : current(), location(shader.getUniformLocation(name)) {
+ static State state(const ProgramID& id) {
+ return State { { uniformLocation(id, Us::name) }... };
}
- void operator=(const std::array<double, C*R>& t) {
- bool dirty = false;
- for (unsigned int i = 0; i < C*R; i++) {
- if (current[i] != t[i]) {
- current[i] = t[i];
- dirty = true;
- }
- }
- if (dirty) {
- bind(current);
- }
+ static std::function<void ()> binder(State& state, Values&& values_) {
+ return [&state, values = std::move(values_)] () mutable {
+ util::ignore({ (state.template get<Us>() = values.template get<Us>(), 0)... });
+ };
}
-
-private:
- void bind(const T&);
-
- T current;
- UniformLocation location;
};
} // namespace gl
diff --git a/src/mbgl/gl/value.cpp b/src/mbgl/gl/value.cpp
index 14cd03efc4..603d82dfd5 100644
--- a/src/mbgl/gl/value.cpp
+++ b/src/mbgl/gl/value.cpp
@@ -22,7 +22,7 @@ ClearDepth::Type ClearDepth::Get() {
return clearDepth;
}
-const constexpr ClearColor::Type ClearColor::Default;
+const ClearColor::Type ClearColor::Default { 0, 0, 0, 0 };
void ClearColor::Set(const Type& value) {
MBGL_CHECK_ERROR(glClearColor(value.r, value.g, value.b, value.a));
@@ -94,7 +94,7 @@ StencilFunc::Type StencilFunc::Get() {
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_FUNC, &func));
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_REF, &ref));
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask));
- return { static_cast<StencilTestFunction>(func), ref, static_cast<StencilMaskValue>(mask) };
+ return { static_cast<uint32_t>(func), ref, static_cast<uint32_t>(mask) };
}
const constexpr StencilTest::Type StencilTest::Default;
@@ -122,17 +122,17 @@ StencilOp::Type StencilOp::Get() {
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_FAIL, &sfail));
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &dpfail));
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &dppass));
- return { static_cast<StencilTestOperation>(sfail), static_cast<StencilTestOperation>(dpfail),
- static_cast<StencilTestOperation>(dppass) };
+ return { static_cast<StencilMode::Op>(sfail), static_cast<StencilMode::Op>(dpfail),
+ static_cast<StencilMode::Op>(dppass) };
}
const constexpr DepthRange::Type DepthRange::Default;
void DepthRange::Set(const Type& value) {
#if MBGL_USE_GLES2
- MBGL_CHECK_ERROR(glDepthRangef(value.near, value.far));
+ MBGL_CHECK_ERROR(glDepthRangef(value.min, value.max));
#else
- MBGL_CHECK_ERROR(glDepthRange(value.near, value.far));
+ MBGL_CHECK_ERROR(glDepthRange(value.min, value.max));
#endif
}
@@ -178,6 +178,18 @@ Blend::Type Blend::Get() {
return blend;
}
+const constexpr BlendEquation::Type BlendEquation::Default;
+
+void BlendEquation::Set(const Type& value) {
+ MBGL_CHECK_ERROR(glBlendEquation(static_cast<GLenum>(value)));
+}
+
+BlendEquation::Type BlendEquation::Get() {
+ GLint blend;
+ MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_EQUATION_RGB, &blend));
+ return static_cast<Type>(blend);
+}
+
const constexpr BlendFunc::Type BlendFunc::Default;
void BlendFunc::Set(const Type& value) {
@@ -189,11 +201,11 @@ BlendFunc::Type BlendFunc::Get() {
GLint sfactor, dfactor;
MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_SRC_ALPHA, &sfactor));
MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_DST_ALPHA, &dfactor));
- return { static_cast<BlendSourceFactor>(sfactor),
- static_cast<BlendDestinationFactor>(dfactor) };
+ return { static_cast<ColorMode::BlendFactor>(sfactor),
+ static_cast<ColorMode::BlendFactor>(dfactor) };
}
-const constexpr BlendColor::Type BlendColor::Default;
+const BlendColor::Type BlendColor::Default { 0, 0, 0, 0 };
void BlendColor::Set(const Type& value) {
MBGL_CHECK_ERROR(glBlendColor(value.r, value.g, value.b, value.a));
@@ -244,14 +256,14 @@ ActiveTexture::Type ActiveTexture::Get() {
const constexpr Viewport::Type Viewport::Default;
void Viewport::Set(const Type& value) {
- MBGL_CHECK_ERROR(glViewport(value.x, value.y, value.width, value.height));
+ MBGL_CHECK_ERROR(glViewport(value.x, value.y, value.size.width, value.size.height));
}
Viewport::Type Viewport::Get() {
GLint viewport[4];
MBGL_CHECK_ERROR(glGetIntegerv(GL_VIEWPORT, viewport));
return { static_cast<int32_t>(viewport[0]), static_cast<int32_t>(viewport[1]),
- static_cast<uint16_t>(viewport[2]), static_cast<uint16_t>(viewport[3]) };
+ { static_cast<uint32_t>(viewport[2]), static_cast<uint32_t>(viewport[3]) } };
}
const constexpr BindFramebuffer::Type BindFramebuffer::Default;
@@ -340,6 +352,18 @@ BindVertexArray::Type BindVertexArray::Get() {
#if not MBGL_USE_GLES2
+const constexpr PointSize::Type PointSize::Default;
+
+void PointSize::Set(const Type& value) {
+ MBGL_CHECK_ERROR(glPointSize(value));
+}
+
+PointSize::Type PointSize::Get() {
+ GLfloat pointSize;
+ MBGL_CHECK_ERROR(glGetFloatv(GL_POINT_SIZE, &pointSize));
+ return pointSize;
+}
+
const constexpr PixelZoom::Type PixelZoom::Default;
void PixelZoom::Set(const Type& value) {
@@ -365,8 +389,63 @@ RasterPos::Type RasterPos::Get() {
return { pos[0], pos[1], pos[2], pos[3] };
}
-#endif // MBGL_USE_GLES2
+const constexpr PixelStorePack::Type PixelStorePack::Default;
+
+void PixelStorePack::Set(const Type& value) {
+ assert(value.alignment == 1 || value.alignment == 2 || value.alignment == 4 ||
+ value.alignment == 8);
+ MBGL_CHECK_ERROR(glPixelStorei(GL_PACK_ALIGNMENT, value.alignment));
+}
+
+PixelStorePack::Type PixelStorePack::Get() {
+ Type value;
+ MBGL_CHECK_ERROR(glGetIntegerv(GL_PACK_ALIGNMENT, &value.alignment));
+ return value;
+}
+
+const constexpr PixelStoreUnpack::Type PixelStoreUnpack::Default;
+void PixelStoreUnpack::Set(const Type& value) {
+ assert(value.alignment == 1 || value.alignment == 2 || value.alignment == 4 ||
+ value.alignment == 8);
+ MBGL_CHECK_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, value.alignment));
+}
+
+PixelStoreUnpack::Type PixelStoreUnpack::Get() {
+ Type value;
+ MBGL_CHECK_ERROR(glGetIntegerv(GL_UNPACK_ALIGNMENT, &value.alignment));
+ return value;
+}
+
+const constexpr PixelTransferDepth::Type PixelTransferDepth::Default;
+
+void PixelTransferDepth::Set(const Type& value) {
+ MBGL_CHECK_ERROR(glPixelTransferf(GL_DEPTH_SCALE, value.scale));
+ MBGL_CHECK_ERROR(glPixelTransferf(GL_DEPTH_BIAS, value.bias));
+}
+
+PixelTransferDepth::Type PixelTransferDepth::Get() {
+ Type value;
+ MBGL_CHECK_ERROR(glGetFloatv(GL_DEPTH_SCALE, &value.scale));
+ MBGL_CHECK_ERROR(glGetFloatv(GL_DEPTH_BIAS, &value.bias));
+ return value;
+}
+
+const constexpr PixelTransferStencil::Type PixelTransferStencil::Default;
+
+void PixelTransferStencil::Set(const Type& value) {
+ MBGL_CHECK_ERROR(glPixelTransferf(GL_INDEX_SHIFT, value.shift));
+ MBGL_CHECK_ERROR(glPixelTransferf(GL_INDEX_OFFSET, value.offset));
+}
+
+PixelTransferStencil::Type PixelTransferStencil::Get() {
+ Type value;
+ MBGL_CHECK_ERROR(glGetIntegerv(GL_INDEX_SHIFT, &value.shift));
+ MBGL_CHECK_ERROR(glGetIntegerv(GL_INDEX_OFFSET, &value.offset));
+ return value;
+}
+
+#endif // MBGL_USE_GLES2
} // namespace value
} // namespace gl
diff --git a/src/mbgl/gl/value.hpp b/src/mbgl/gl/value.hpp
index 866ce389a4..eccd3e7373 100644
--- a/src/mbgl/gl/value.hpp
+++ b/src/mbgl/gl/value.hpp
@@ -1,7 +1,12 @@
#pragma once
#include <mbgl/gl/types.hpp>
+#include <mbgl/gl/depth_mode.hpp>
+#include <mbgl/gl/stencil_mode.hpp>
+#include <mbgl/gl/color_mode.hpp>
#include <mbgl/util/color.hpp>
+#include <mbgl/util/size.hpp>
+#include <mbgl/util/range.hpp>
namespace mbgl {
namespace gl {
@@ -16,20 +21,20 @@ struct ClearDepth {
struct ClearColor {
using Type = Color;
- static const constexpr Type Default = { 0, 0, 0, 0 };
+ static const Type Default;
static void Set(const Type&);
static Type Get();
};
struct ClearStencil {
- using Type = StencilValue;
+ using Type = int32_t;
static const constexpr Type Default = 0;
static void Set(const Type&);
static Type Get();
};
struct StencilMask {
- using Type = StencilMaskValue;
+ using Type = uint32_t;
static const constexpr Type Default = ~0u;
static void Set(const Type&);
static Type Get();
@@ -43,28 +48,19 @@ struct DepthMask {
};
struct ColorMask {
- struct Type {
- bool r;
- bool g;
- bool b;
- bool a;
- };
+ using Type = ColorMode::Mask;
static const constexpr Type Default = { true, true, true, true };
static void Set(const Type&);
static Type Get();
};
-constexpr bool operator!=(const ColorMask::Type& a, const ColorMask::Type& b) {
- return a.r != b.r || a.g != b.g || a.b != b.b || a.a != b.a;
-}
-
struct StencilFunc {
struct Type {
- StencilTestFunction func;
- StencilValue ref;
- StencilMaskValue mask;
+ uint32_t func;
+ int32_t ref;
+ uint32_t mask;
};
- static const constexpr Type Default = { StencilTestFunction::Always, 0, ~0u };
+ static const constexpr Type Default = { StencilMode::Always::func, 0, ~0u };
static void Set(const Type&);
static Type Get();
};
@@ -82,12 +78,11 @@ struct StencilTest {
struct StencilOp {
struct Type {
- StencilTestOperation sfail;
- StencilTestOperation dpfail;
- StencilTestOperation dppass;
+ StencilMode::Op sfail;
+ StencilMode::Op dpfail;
+ StencilMode::Op dppass;
};
- static const constexpr Type Default = { StencilTestOperation::Keep, StencilTestOperation::Keep,
- StencilTestOperation::Keep };
+ static const constexpr Type Default = { StencilMode::Keep, StencilMode::Keep, StencilMode::Keep };
static void Set(const Type&);
static Type Get();
};
@@ -97,19 +92,12 @@ constexpr bool operator!=(const StencilOp::Type& a, const StencilOp::Type& b) {
}
struct DepthRange {
- struct Type {
- float near;
- float far;
- };
+ using Type = Range<float>;
static const constexpr Type Default = { 0, 1 };
static void Set(const Type&);
static Type Get();
};
-constexpr bool operator!=(const DepthRange::Type& a, const DepthRange::Type& b) {
- return a.near != b.near || a.far != b.far;
-}
-
struct DepthTest {
using Type = bool;
static const constexpr Type Default = false;
@@ -118,8 +106,8 @@ struct DepthTest {
};
struct DepthFunc {
- using Type = DepthTestFunction;
- static const constexpr Type Default = DepthTestFunction::Less;
+ using Type = DepthMode::Function;
+ static const constexpr Type Default = DepthMode::Less;
static void Set(const Type&);
static Type Get();
};
@@ -131,12 +119,19 @@ struct Blend {
static Type Get();
};
+struct BlendEquation {
+ using Type = ColorMode::BlendEquation;
+ static const constexpr Type Default = ColorMode::BlendEquation::Add;
+ static void Set(const Type&);
+ static Type Get();
+};
+
struct BlendFunc {
struct Type {
- BlendSourceFactor sfactor;
- BlendDestinationFactor dfactor;
+ ColorMode::BlendFactor sfactor;
+ ColorMode::BlendFactor dfactor;
};
- static const constexpr Type Default = { BlendSourceFactor::One, BlendDestinationFactor::Zero };
+ static const constexpr Type Default = { ColorMode::One, ColorMode::Zero };
static void Set(const Type&);
static Type Get();
};
@@ -147,7 +142,7 @@ constexpr bool operator!=(const BlendFunc::Type& a, const BlendFunc::Type& b) {
struct BlendColor {
using Type = Color;
- static const constexpr Type Default = { 0, 0, 0, 0 };
+ static const Type Default;
static void Set(const Type&);
static Type Get();
};
@@ -177,16 +172,19 @@ struct Viewport {
struct Type {
int32_t x;
int32_t y;
- uint16_t width;
- uint16_t height;
+ Size size;
};
- static const constexpr Type Default = { 0, 0, 0, 0 };
+ static const constexpr Type Default = { 0, 0, { 0, 0 } };
static void Set(const Type&);
static Type Get();
};
constexpr bool operator!=(const Viewport::Type& a, const Viewport::Type& b) {
- return a.x != b.x || a.y != b.y || a.width != b.width || a.height != b.height;
+ return a.x != b.x || a.y != b.y || a.size != b.size;
+}
+
+constexpr bool operator==(const Viewport::Type& a, const Viewport::Type& b) {
+ return !(a != b);
}
struct BindFramebuffer {
@@ -233,6 +231,13 @@ struct BindVertexArray {
#if not MBGL_USE_GLES2
+struct PointSize {
+ using Type = float;
+ static const constexpr Type Default = 1;
+ static void Set(const Type&);
+ static Type Get();
+};
+
struct PixelZoom {
struct Type {
float xfactor;
@@ -254,7 +259,7 @@ struct RasterPos {
double z;
double w;
};
- static const constexpr Type Default = { 0, 0, 0, 0 };
+ static const constexpr Type Default = { 0, 0, 0, 1 };
static void Set(const Type&);
static Type Get();
};
@@ -263,6 +268,48 @@ constexpr bool operator!=(const RasterPos::Type& a, const RasterPos::Type& b) {
return a.x != b.x || a.y != b.y || a.z != b.z || a.w != b.w;
}
+struct PixelStorePack {
+ using Type = PixelStorageType;
+ static const constexpr Type Default = { 4 };
+ static void Set(const Type&);
+ static Type Get();
+};
+
+struct PixelStoreUnpack {
+ using Type = PixelStorageType;
+ static const constexpr Type Default = { 4 };
+ static void Set(const Type&);
+ static Type Get();
+};
+
+struct PixelTransferDepth {
+ struct Type {
+ float scale;
+ float bias;
+ };
+ static const constexpr Type Default = { 1, 0 };
+ static void Set(const Type&);
+ static Type Get();
+};
+
+constexpr bool operator!=(const PixelTransferDepth::Type& a, const PixelTransferDepth::Type& b) {
+ return a.scale != b.scale || a.bias != b.bias;
+}
+
+struct PixelTransferStencil {
+ struct Type {
+ int32_t shift;
+ int32_t offset;
+ };
+ static const constexpr Type Default = { 0, 0 };
+ static void Set(const Type&);
+ static Type Get();
+};
+
+constexpr bool operator!=(const PixelTransferStencil::Type& a, const PixelTransferStencil::Type& b) {
+ return a.shift != b.shift || a.offset != b.offset;
+}
+
#endif // MBGL_USE_GLES2
} // namespace value
diff --git a/src/mbgl/gl/vao.cpp b/src/mbgl/gl/vao.cpp
deleted file mode 100644
index b235b0e63b..0000000000
--- a/src/mbgl/gl/vao.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <mbgl/gl/vao.hpp>
-#include <mbgl/gl/vertex_array.hpp>
-#include <mbgl/platform/log.hpp>
-#include <mbgl/util/string.hpp>
-#include <mbgl/gl/gl.hpp>
-
-namespace mbgl {
-namespace gl {
-
-void VertexArrayObject::bindVertexArrayObject(Context& context) {
- if (!GenVertexArrays || !BindVertexArray) {
- static bool reported = false;
- if (!reported) {
- Log::Warning(Event::OpenGL, "Not using Vertex Array Objects");
- reported = true;
- }
- return;
- }
-
- if (!vertexArray) {
- vertexArray = context.createVertexArray();
- context.vertexBuffer.setDirty();
- context.elementBuffer.setDirty();
- }
-
- context.vertexArrayObject = *vertexArray;
-}
-
-void VertexArrayObject::verifyBinding(Shader& shader,
- BufferID vertexBuffer,
- BufferID elementsBuffer,
- int8_t* offset) {
- if (bound_shader != shader.getID()) {
- throw std::runtime_error(std::string("trying to rebind VAO to another shader from " +
- util::toString(bound_shader) + "(" + bound_shader_name + ") to " +
- util::toString(shader.getID()) + "(" + shader.name + ")" ));
- } else if (bound_offset != offset) {
- throw std::runtime_error("trying to bind VAO to another offset");
- } else if (bound_vertex_buffer != vertexBuffer) {
- throw std::runtime_error("trying to bind VAO to another vertex buffer");
- } else if (bound_elements_buffer != elementsBuffer) {
- throw std::runtime_error("trying to bind VAO to another elements buffer");
- }
-}
-
-void VertexArrayObject::storeBinding(Shader& shader,
- BufferID vertexBuffer,
- BufferID elementsBuffer,
- int8_t* offset) {
- bound_shader = shader.getID();
- bound_shader_name = shader.name;
- bound_offset = offset;
- bound_vertex_buffer = vertexBuffer;
- bound_elements_buffer = elementsBuffer;
-}
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/gl/vao.hpp b/src/mbgl/gl/vao.hpp
deleted file mode 100644
index 826c028d32..0000000000
--- a/src/mbgl/gl/vao.hpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/context.hpp>
-#include <mbgl/gl/vertex_buffer.hpp>
-#include <mbgl/util/optional.hpp>
-
-#include <stdexcept>
-
-namespace mbgl {
-namespace gl {
-
-class VertexArrayObject {
-public:
- template <typename Shader, typename T>
- void bind(Shader& shader,
- const VertexBuffer<T>& vertexBuffer,
- int8_t* offset,
- Context& context) {
- bindVertexArrayObject(context);
- if (bound_shader == 0) {
- context.vertexBuffer = vertexBuffer.buffer;
- context.bindAttributes(shader, vertexBuffer, offset);
- if (vertexArray) {
- storeBinding(shader, vertexBuffer.buffer, 0, offset);
- }
- } else {
- verifyBinding(shader, vertexBuffer.buffer, 0, offset);
- }
- }
-
- template <typename Shader, typename T, typename P>
- void bind(Shader& shader,
- const VertexBuffer<T>& vertexBuffer,
- const IndexBuffer<P>& indexBuffer,
- int8_t* offset,
- Context& context) {
- bindVertexArrayObject(context);
- if (bound_shader == 0) {
- context.vertexBuffer = vertexBuffer.buffer;
- context.elementBuffer = indexBuffer.buffer;
- context.bindAttributes(shader, vertexBuffer, offset);
- if (vertexArray) {
- storeBinding(shader, vertexBuffer.buffer, indexBuffer.buffer, offset);
- }
- } else {
- verifyBinding(shader, vertexBuffer.buffer, indexBuffer.buffer, offset);
- }
- }
-
- VertexArrayID getID() const {
- return *vertexArray;
- }
-
-private:
- void bindVertexArrayObject(Context&);
- void storeBinding(Shader& shader,
- BufferID vertexBuffer,
- BufferID elementsBuffer,
- int8_t* offset);
- void verifyBinding(Shader& shader,
- BufferID vertexBuffer,
- BufferID elementsBuffer,
- int8_t* offset);
-
- optional<UniqueVertexArray> vertexArray;
-
- // For debug reasons, we're storing the bind information so that we can
- // detect errors and report
- ProgramID bound_shader = 0;
- const char* bound_shader_name = "";
- BufferID bound_vertex_buffer = 0;
- BufferID bound_elements_buffer = 0;
- int8_t *bound_offset = nullptr;
-};
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/gl/vertex_buffer.hpp b/src/mbgl/gl/vertex_buffer.hpp
index c77a9a4213..c9bc01f3e8 100644
--- a/src/mbgl/gl/vertex_buffer.hpp
+++ b/src/mbgl/gl/vertex_buffer.hpp
@@ -1,14 +1,43 @@
#pragma once
#include <mbgl/gl/object.hpp>
+#include <mbgl/gl/primitives.hpp>
+#include <mbgl/gl/draw_mode.hpp>
+#include <mbgl/util/ignore.hpp>
+
+#include <vector>
namespace mbgl {
namespace gl {
-template <class Vertex>
+template <class V, class DrawMode = Indexed>
+class VertexVector {
+public:
+ using Vertex = V;
+ static constexpr std::size_t groupSize = DrawMode::bufferGroupSize;
+
+ template <class... Args>
+ void emplace_back(Args&&... args) {
+ static_assert(sizeof...(args) == groupSize, "wrong buffer element count");
+ util::ignore({(v.emplace_back(std::forward<Args>(args)), 0)...});
+ }
+
+ std::size_t vertexSize() const { return v.size(); }
+ std::size_t byteSize() const { return v.size() * sizeof(Vertex); }
+
+ bool empty() const { return v.empty(); }
+ const Vertex* data() const { return v.data(); }
+
+private:
+ std::vector<Vertex> v;
+};
+
+template <class V, class DrawMode = Indexed>
class VertexBuffer {
public:
+ using Vertex = V;
static constexpr std::size_t vertexSize = sizeof(Vertex);
+
std::size_t vertexCount;
UniqueBuffer buffer;
};
diff --git a/src/mbgl/layout/merge_lines.cpp b/src/mbgl/layout/merge_lines.cpp
index f4fdb82617..676cbc092d 100644
--- a/src/mbgl/layout/merge_lines.cpp
+++ b/src/mbgl/layout/merge_lines.cpp
@@ -47,10 +47,10 @@ enum class Side {
};
size_t
-getKey(const std::u32string& text, const GeometryCollection& geom, Side side) {
+getKey(const std::u16string& text, const GeometryCollection& geom, Side side) {
const GeometryCoordinate& coord = side == Side::Right ? geom[0].back() : geom[0].front();
- auto hash = std::hash<std::u32string>()(text);
+ auto hash = std::hash<std::u16string>()(text);
boost::hash_combine(hash, coord.x);
boost::hash_combine(hash, coord.y);
return hash;
diff --git a/src/mbgl/layout/symbol_feature.hpp b/src/mbgl/layout/symbol_feature.hpp
index 99db4f9ac5..5dd61d9156 100644
--- a/src/mbgl/layout/symbol_feature.hpp
+++ b/src/mbgl/layout/symbol_feature.hpp
@@ -9,8 +9,9 @@ namespace mbgl {
class SymbolFeature {
public:
+ FeatureType type;
GeometryCollection geometry;
- optional<std::u32string> text;
+ optional<std::u16string> text;
optional<std::string> icon;
std::size_t index;
};
diff --git a/src/mbgl/layout/symbol_instance.cpp b/src/mbgl/layout/symbol_instance.cpp
index 64b913200e..fafcc7c15d 100644
--- a/src/mbgl/layout/symbol_instance.cpp
+++ b/src/mbgl/layout/symbol_instance.cpp
@@ -7,7 +7,7 @@ using namespace style;
SymbolInstance::SymbolInstance(Anchor& anchor, const GeometryCoordinates& line,
const Shaping& shapedText, const PositionedIcon& shapedIcon,
- const SymbolLayoutProperties& layout, const bool addToBuffers, const uint32_t index_,
+ const SymbolLayoutProperties::Evaluated& layout, const bool addToBuffers, const uint32_t index_,
const float textBoxScale, const float textPadding, const SymbolPlacementType textPlacement,
const float iconBoxScale, const float iconPadding, const SymbolPlacementType iconPlacement,
const GlyphPositions& face, const IndexedSubfeature& indexedFeature) :
diff --git a/src/mbgl/layout/symbol_instance.hpp b/src/mbgl/layout/symbol_instance.hpp
index 3087bf09f9..508c11a394 100644
--- a/src/mbgl/layout/symbol_instance.hpp
+++ b/src/mbgl/layout/symbol_instance.hpp
@@ -2,21 +2,18 @@
#include <mbgl/text/quads.hpp>
#include <mbgl/text/collision_feature.hpp>
+#include <mbgl/style/layers/symbol_layer_properties.hpp>
namespace mbgl {
struct Anchor;
class IndexedSubfeature;
-namespace style {
-class SymbolLayoutProperties;
-} // namespace style
-
class SymbolInstance {
public:
explicit SymbolInstance(Anchor& anchor, const GeometryCoordinates& line,
const Shaping& shapedText, const PositionedIcon& shapedIcon,
- const style::SymbolLayoutProperties&, const bool inside, const uint32_t index,
+ const style::SymbolLayoutProperties::Evaluated&, const bool inside, const uint32_t index,
const float textBoxScale, const float textPadding, style::SymbolPlacementType textPlacement,
const float iconBoxScale, const float iconPadding, style::SymbolPlacementType iconPlacement,
const GlyphPositions& face, const IndexedSubfeature& indexedfeature);
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index 07ba2bf4a3..eaa0332995 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -3,6 +3,7 @@
#include <mbgl/layout/clip_lines.hpp>
#include <mbgl/renderer/symbol_bucket.hpp>
#include <mbgl/style/filter_evaluator.hpp>
+#include <mbgl/style/layer.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/text/get_anchors.hpp>
@@ -11,30 +12,32 @@
#include <mbgl/util/constants.hpp>
#include <mbgl/util/utf.hpp>
#include <mbgl/util/token.hpp>
-#include <mbgl/util/math.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/math/clamp.hpp>
#include <mbgl/math/minmax.hpp>
-#include <mbgl/platform/platform.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/math/log2.hpp>
+#include <mbgl/util/platform.hpp>
+#include <mbgl/util/logging.hpp>
+
+#include <mapbox/polylabel.hpp>
namespace mbgl {
using namespace style;
-SymbolLayout::SymbolLayout(std::string bucketName_,
+SymbolLayout::SymbolLayout(std::vector<std::string> layerIDs_,
std::string sourceLayerName_,
uint32_t overscaling_,
float zoom_,
const MapMode mode_,
const GeometryTileLayer& layer,
const style::Filter& filter,
- style::SymbolLayoutProperties layout_,
+ style::SymbolLayoutProperties::Evaluated layout_,
float textMaxSize_,
SpriteAtlas& spriteAtlas_)
- : bucketName(std::move(bucketName_)),
+ : layerIDs(std::move(layerIDs_)),
sourceLayerName(std::move(sourceLayerName_)),
overscaling(overscaling_),
zoom(zoom_),
@@ -45,8 +48,8 @@ SymbolLayout::SymbolLayout(std::string bucketName_,
tileSize(util::tileSize * overscaling_),
tilePixelRatio(float(util::EXTENT) / tileSize) {
- const bool hasText = !layout.textField.value.empty() && !layout.textFont.value.empty();
- const bool hasIcon = !layout.iconImage.value.empty();
+ const bool hasText = !layout.get<TextField>().empty() && !layout.get<TextFont>().empty();
+ const bool hasIcon = !layout.get<IconImage>().empty();
if (!hasText && !hasIcon) {
return;
@@ -82,42 +85,34 @@ SymbolLayout::SymbolLayout(std::string bucketName_,
};
if (hasText) {
- std::string u8string = util::replaceTokens(layout.textField, getValue);
+ std::string u8string = util::replaceTokens(layout.get<TextField>(), getValue);
- if (layout.textTransform == TextTransformType::Uppercase) {
+ if (layout.get<TextTransform>() == TextTransformType::Uppercase) {
u8string = platform::uppercase(u8string);
- } else if (layout.textTransform == TextTransformType::Lowercase) {
+ } else if (layout.get<TextTransform>() == TextTransformType::Lowercase) {
u8string = platform::lowercase(u8string);
}
- ft.text = util::utf8_to_utf32::convert(u8string);
+ ft.text = applyArabicShaping(util::utf8_to_utf16::convert(u8string));
// Loop through all characters of this text and collect unique codepoints.
- for (char32_t chr : *ft.text) {
+ for (char16_t chr : *ft.text) {
ranges.insert(getGlyphRange(chr));
}
}
if (hasIcon) {
- ft.icon = util::replaceTokens(layout.iconImage, getValue);
+ ft.icon = util::replaceTokens(layout.get<IconImage>(), getValue);
}
if (ft.text || ft.icon) {
- auto &multiline = ft.geometry;
-
- GeometryCollection geometryCollection = feature->getGeometries();
- for (auto& line : geometryCollection) {
- multiline.emplace_back();
- for (auto& point : line) {
- multiline.back().emplace_back(point.x, point.y);
- }
- }
-
+ ft.type = feature->getType();
+ ft.geometry = feature->getGeometries();
features.push_back(std::move(ft));
}
}
- if (layout.symbolPlacement == SymbolPlacementType::Line) {
+ if (layout.get<SymbolPlacement>() == SymbolPlacementType::Line) {
util::mergeLines(features);
}
}
@@ -127,11 +122,11 @@ bool SymbolLayout::hasSymbolInstances() const {
}
bool SymbolLayout::canPrepare(GlyphAtlas& glyphAtlas) {
- if (!layout.textField.value.empty() && !layout.textFont.value.empty() && !glyphAtlas.hasGlyphRanges(layout.textFont, ranges)) {
+ if (!layout.get<TextField>().empty() && !layout.get<TextFont>().empty() && !glyphAtlas.hasGlyphRanges(layout.get<TextFont>(), ranges)) {
return false;
}
- if (!layout.iconImage.value.empty() && !spriteAtlas.isLoaded()) {
+ if (!layout.get<IconImage>().empty() && !spriteAtlas.isLoaded()) {
return false;
}
@@ -143,7 +138,7 @@ void SymbolLayout::prepare(uintptr_t tileUID,
float horizontalAlign = 0.5;
float verticalAlign = 0.5;
- switch (layout.textAnchor) {
+ switch (layout.get<TextAnchor>()) {
case TextAnchorType::Top:
case TextAnchorType::Bottom:
case TextAnchorType::Center:
@@ -160,7 +155,7 @@ void SymbolLayout::prepare(uintptr_t tileUID,
break;
}
- switch (layout.textAnchor) {
+ switch (layout.get<TextAnchor>()) {
case TextAnchorType::Left:
case TextAnchorType::Right:
case TextAnchorType::Center:
@@ -177,11 +172,11 @@ void SymbolLayout::prepare(uintptr_t tileUID,
break;
}
- const float justify = layout.textJustify == TextJustifyType::Right ? 1 :
- layout.textJustify == TextJustifyType::Left ? 0 :
+ const float justify = layout.get<TextJustify>() == TextJustifyType::Right ? 1 :
+ layout.get<TextJustify>() == TextJustifyType::Left ? 0 :
0.5;
- auto glyphSet = glyphAtlas.getGlyphSet(layout.textFont);
+ auto glyphSet = glyphAtlas.getGlyphSet(layout.get<TextFont>());
for (const auto& feature : features) {
if (feature.geometry.empty()) continue;
@@ -194,18 +189,19 @@ void SymbolLayout::prepare(uintptr_t tileUID,
if (feature.text) {
shapedText = glyphSet->getShaping(
/* string */ *feature.text,
- /* maxWidth: ems */ layout.symbolPlacement != SymbolPlacementType::Line ?
- layout.textMaxWidth * 24 : 0,
- /* lineHeight: ems */ layout.textLineHeight * 24,
+ /* maxWidth: ems */ layout.get<SymbolPlacement>() != SymbolPlacementType::Line ?
+ layout.get<TextMaxWidth>() * 24 : 0,
+ /* lineHeight: ems */ layout.get<TextLineHeight>() * 24,
/* horizontalAlign */ horizontalAlign,
/* verticalAlign */ verticalAlign,
/* justify */ justify,
- /* spacing: ems */ layout.textLetterSpacing * 24,
- /* translate */ Point<float>(layout.textOffset.value[0], layout.textOffset.value[1]));
+ /* spacing: ems */ layout.get<TextLetterSpacing>() * 24,
+ /* translate */ Point<float>(layout.get<TextOffset>()[0], layout.get<TextOffset>()[1]),
+ /* bidirectional algorithm object */ bidi);
// Add the glyphs we need for this label to the glyph atlas.
if (shapedText) {
- glyphAtlas.addGlyphs(tileUID, *feature.text, layout.textFont, **glyphSet, face);
+ glyphAtlas.addGlyphs(tileUID, *feature.text, layout.get<TextFont>(), **glyphSet, face);
}
}
@@ -220,7 +216,7 @@ void SymbolLayout::prepare(uintptr_t tileUID,
}
if ((*image).relativePixelRatio != 1.0f) {
iconsNeedLinear = true;
- } else if (layout.iconRotate != 0) {
+ } else if (layout.get<IconRotate>() != 0) {
iconsNeedLinear = true;
}
}
@@ -228,93 +224,122 @@ void SymbolLayout::prepare(uintptr_t tileUID,
// if either shapedText or icon position is present, add the feature
if (shapedText || shapedIcon) {
- addFeature(feature.geometry, shapedText, shapedIcon, face, feature.index);
+ addFeature(feature, shapedText, shapedIcon, face);
}
}
features.clear();
}
-
-void SymbolLayout::addFeature(const GeometryCollection &lines,
- const Shaping &shapedText, const PositionedIcon &shapedIcon, const GlyphPositions &face, const size_t index) {
-
+void SymbolLayout::addFeature(const SymbolFeature& feature,
+ const Shaping& shapedText,
+ const PositionedIcon& shapedIcon,
+ const GlyphPositions& face) {
const float minScale = 0.5f;
const float glyphSize = 24.0f;
- const float fontScale = layout.textSize / glyphSize;
+ const float fontScale = layout.get<TextSize>() / glyphSize;
const float textBoxScale = tilePixelRatio * fontScale;
const float textMaxBoxScale = tilePixelRatio * textMaxSize / glyphSize;
- const float iconBoxScale = tilePixelRatio * layout.iconSize;
- const float symbolSpacing = tilePixelRatio * layout.symbolSpacing;
- const bool avoidEdges = layout.symbolAvoidEdges && layout.symbolPlacement != SymbolPlacementType::Line;
- const float textPadding = layout.textPadding * tilePixelRatio;
- const float iconPadding = layout.iconPadding * tilePixelRatio;
- const float textMaxAngle = layout.textMaxAngle * util::DEG2RAD;
- const SymbolPlacementType textPlacement = layout.textRotationAlignment != AlignmentType::Map
+ const float iconBoxScale = tilePixelRatio * layout.get<IconSize>();
+ const float symbolSpacing = tilePixelRatio * layout.get<SymbolSpacing>();
+ const bool avoidEdges = layout.get<SymbolAvoidEdges>() && layout.get<SymbolPlacement>() != SymbolPlacementType::Line;
+ const float textPadding = layout.get<TextPadding>() * tilePixelRatio;
+ const float iconPadding = layout.get<IconPadding>() * tilePixelRatio;
+ const float textMaxAngle = layout.get<TextMaxAngle>() * util::DEG2RAD;
+ const SymbolPlacementType textPlacement = layout.get<TextRotationAlignment>() != AlignmentType::Map
? SymbolPlacementType::Point
- : layout.symbolPlacement;
- const SymbolPlacementType iconPlacement = layout.iconRotationAlignment != AlignmentType::Map
+ : layout.get<SymbolPlacement>();
+ const SymbolPlacementType iconPlacement = layout.get<IconRotationAlignment>() != AlignmentType::Map
? SymbolPlacementType::Point
- : layout.symbolPlacement;
- const bool mayOverlap = layout.textAllowOverlap || layout.iconAllowOverlap ||
- layout.textIgnorePlacement || layout.iconIgnorePlacement;
- const bool isLine = layout.symbolPlacement == SymbolPlacementType::Line;
+ : layout.get<SymbolPlacement>();
const float textRepeatDistance = symbolSpacing / 2;
-
- auto& clippedLines = isLine ?
- util::clipLines(lines, 0, 0, util::EXTENT, util::EXTENT) :
- lines;
-
- IndexedSubfeature indexedFeature = {index, sourceLayerName, bucketName, symbolInstances.size()};
-
- for (const auto& line : clippedLines) {
- if (line.empty()) continue;
-
- // Calculate the anchor points around which you want to place labels
- Anchors anchors = isLine ?
- getAnchors(line, symbolSpacing, textMaxAngle, shapedText.left, shapedText.right, shapedIcon.left, shapedIcon.right, glyphSize, textMaxBoxScale, overscaling) :
- Anchors({ Anchor(float(line[0].x), float(line[0].y), 0, minScale) });
-
- // For each potential label, create the placement features used to check for collisions, and the quads use for rendering.
- for (Anchor &anchor : anchors) {
- if (shapedText && isLine) {
- if (anchorIsTooClose(shapedText.text, textRepeatDistance, anchor)) {
- continue;
+ IndexedSubfeature indexedFeature = {feature.index, sourceLayerName, layerIDs.at(0), symbolInstances.size()};
+
+ auto addSymbolInstance = [&] (const GeometryCoordinates& line, Anchor& anchor) {
+ // https://github.com/mapbox/vector-tile-spec/tree/master/2.1#41-layers
+ // +-------------------+ Symbols with anchors located on tile edges
+ // |(0,0) || are duplicated on neighbor tiles.
+ // | ||
+ // | || In continuous mode, to avoid overdraw we
+ // | || skip symbols located on the extent edges.
+ // | Tile || In still mode, we include the features in
+ // | || the buffers for both tiles and clip them
+ // | || at draw time.
+ // | ||
+ // +-------------------| In this scenario, the inner bounding box
+ // +-------------------+ is called 'withinPlus0', and the outer
+ // (extent,extent) is called 'inside'.
+ const bool withinPlus0 = anchor.point.x >= 0 && anchor.point.x < util::EXTENT && anchor.point.y >= 0 && anchor.point.y < util::EXTENT;
+ const bool inside = withinPlus0 || anchor.point.x == util::EXTENT || anchor.point.y == util::EXTENT;
+
+ if (avoidEdges && !inside) return;
+
+ const bool addToBuffers = mode == MapMode::Still || withinPlus0;
+
+ symbolInstances.emplace_back(anchor, line, shapedText, shapedIcon, layout, addToBuffers, symbolInstances.size(),
+ textBoxScale, textPadding, textPlacement,
+ iconBoxScale, iconPadding, iconPlacement,
+ face, indexedFeature);
+ };
+
+ if (layout.get<SymbolPlacement>() == SymbolPlacementType::Line) {
+ auto clippedLines = util::clipLines(feature.geometry, 0, 0, util::EXTENT, util::EXTENT);
+ for (const auto& line : clippedLines) {
+ Anchors anchors = getAnchors(line,
+ symbolSpacing,
+ textMaxAngle,
+ shapedText.left,
+ shapedText.right,
+ shapedIcon.left,
+ shapedIcon.right,
+ glyphSize,
+ textMaxBoxScale,
+ overscaling);
+
+ for (auto& anchor : anchors) {
+ if (!shapedText || !anchorIsTooClose(shapedText.text, textRepeatDistance, anchor)) {
+ addSymbolInstance(line, anchor);
}
}
+ }
+ } else if (feature.type == FeatureType::Polygon) {
+ for (const auto& polygon : classifyRings(feature.geometry)) {
+ Polygon<double> poly;
+ for (const auto& ring : polygon) {
+ LinearRing<double> r;
+ for (const auto& p : ring) {
+ r.push_back(convertPoint<double>(p));
+ }
+ poly.push_back(r);
+ }
- const bool inside = !(anchor.point.x < 0 || anchor.point.x > util::EXTENT || anchor.point.y < 0 || anchor.point.y > util::EXTENT);
-
- if (avoidEdges && !inside) continue;
-
- // Normally symbol layers are drawn across tile boundaries. Only symbols
- // with their anchors within the tile boundaries are added to the buffers
- // to prevent symbols from being drawn twice.
- //
- // Symbols in layers with overlap are sorted in the y direction so that
- // symbols lower on the canvas are drawn on top of symbols near the top.
- // To preserve this order across tile boundaries these symbols can't
- // be drawn across tile boundaries. Instead they need to be included in
- // the buffers for both tiles and clipped to tile boundaries at draw time.
- //
- // TODO remove the `&& false` when is #1673 implemented
- const bool addToBuffers = (mode == MapMode::Still) || inside || (mayOverlap && false);
-
- symbolInstances.emplace_back(anchor, line, shapedText, shapedIcon, layout, addToBuffers, symbolInstances.size(),
- textBoxScale, textPadding, textPlacement,
- iconBoxScale, iconPadding, iconPlacement,
- face, indexedFeature);
+ // 1 pixel worth of precision, in tile coordinates
+ auto poi = mapbox::polylabel(poly, double(util::EXTENT / util::tileSize));
+ Anchor anchor(poi.x, poi.y, 0, minScale);
+ addSymbolInstance(polygon[0], anchor);
+ }
+ } else if (feature.type == FeatureType::LineString) {
+ for (const auto& line : feature.geometry) {
+ Anchor anchor(line[0].x, line[0].y, 0, minScale);
+ addSymbolInstance(line, anchor);
+ }
+ } else if (feature.type == FeatureType::Point) {
+ for (const auto& points : feature.geometry) {
+ for (const auto& point : points) {
+ Anchor anchor(point.x, point.y, 0, minScale);
+ addSymbolInstance({point}, anchor);
+ }
}
}
}
-bool SymbolLayout::anchorIsTooClose(const std::u32string &text, const float repeatDistance, Anchor &anchor) {
+bool SymbolLayout::anchorIsTooClose(const std::u16string& text, const float repeatDistance, const Anchor& anchor) {
if (compareText.find(text) == compareText.end()) {
compareText.emplace(text, Anchors());
} else {
auto otherAnchors = compareText.find(text)->second;
- for (Anchor &otherAnchor : otherAnchors) {
+ for (const Anchor& otherAnchor : otherAnchors) {
if (util::dist<float>(anchor.point, otherAnchor.point) < repeatDistance) {
return true;
}
@@ -330,15 +355,15 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
// Calculate which labels can be shown and when they can be shown and
// create the bufers used for rendering.
- const SymbolPlacementType textPlacement = layout.textRotationAlignment != AlignmentType::Map
+ const SymbolPlacementType textPlacement = layout.get<TextRotationAlignment>() != AlignmentType::Map
? SymbolPlacementType::Point
- : layout.symbolPlacement;
- const SymbolPlacementType iconPlacement = layout.iconRotationAlignment != AlignmentType::Map
+ : layout.get<SymbolPlacement>();
+ const SymbolPlacementType iconPlacement = layout.get<IconRotationAlignment>() != AlignmentType::Map
? SymbolPlacementType::Point
- : layout.symbolPlacement;
+ : layout.get<SymbolPlacement>();
- const bool mayOverlap = layout.textAllowOverlap || layout.iconAllowOverlap ||
- layout.textIgnorePlacement || layout.iconIgnorePlacement;
+ const bool mayOverlap = layout.get<TextAllowOverlap>() || layout.get<IconAllowOverlap>() ||
+ layout.get<TextIgnorePlacement>() || layout.get<IconIgnorePlacement>();
// Sort symbols by their y position on the canvas so that they lower symbols
// are drawn on top of higher symbols.
@@ -362,18 +387,18 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
const bool hasText = symbolInstance.hasText;
const bool hasIcon = symbolInstance.hasIcon;
- const bool iconWithoutText = layout.textOptional || !hasText;
- const bool textWithoutIcon = layout.iconOptional || !hasIcon;
+ const bool iconWithoutText = layout.get<TextOptional>() || !hasText;
+ const bool textWithoutIcon = layout.get<IconOptional>() || !hasIcon;
// Calculate the scales at which the text and icon can be placed without collision.
float glyphScale = hasText ?
collisionTile.placeFeature(symbolInstance.textCollisionFeature,
- layout.textAllowOverlap, layout.symbolAvoidEdges) :
+ layout.get<TextAllowOverlap>(), layout.get<SymbolAvoidEdges>()) :
collisionTile.minScale;
float iconScale = hasIcon ?
collisionTile.placeFeature(symbolInstance.iconCollisionFeature,
- layout.iconAllowOverlap, layout.symbolAvoidEdges) :
+ layout.get<IconAllowOverlap>(), layout.get<SymbolAvoidEdges>()) :
collisionTile.minScale;
@@ -391,20 +416,20 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
// Insert final placement into collision tree and add glyphs/icons to buffers
if (hasText) {
- collisionTile.insertFeature(symbolInstance.textCollisionFeature, glyphScale, layout.textIgnorePlacement);
+ collisionTile.insertFeature(symbolInstance.textCollisionFeature, glyphScale, layout.get<TextIgnorePlacement>());
if (glyphScale < collisionTile.maxScale) {
addSymbols(
bucket->text, symbolInstance.glyphQuads, glyphScale,
- layout.textKeepUpright, textPlacement, collisionTile.config.angle);
+ layout.get<TextKeepUpright>(), textPlacement, collisionTile.config.angle);
}
}
if (hasIcon) {
- collisionTile.insertFeature(symbolInstance.iconCollisionFeature, iconScale, layout.iconIgnorePlacement);
+ collisionTile.insertFeature(symbolInstance.iconCollisionFeature, iconScale, layout.get<IconIgnorePlacement>());
if (iconScale < collisionTile.maxScale) {
addSymbols(
bucket->icon, symbolInstance.iconQuads, iconScale,
- layout.iconKeepUpright, iconPlacement, collisionTile.config.angle);
+ layout.get<IconKeepUpright>(), iconPlacement, collisionTile.config.angle);
}
}
}
@@ -418,8 +443,8 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
template <typename Buffer>
void SymbolLayout::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float scale, const bool keepUpright, const style::SymbolPlacementType placement, const float placementAngle) {
-
- const float placementZoom = ::fmax(std::log(scale) / std::log(2) + zoom, 0);
+ constexpr const uint16_t vertexLength = 4;
+ const float placementZoom = util::max(util::log2(scale) + zoom, 0.0f);
for (const auto& symbol : symbols) {
const auto &tl = symbol.tl;
@@ -428,9 +453,8 @@ void SymbolLayout::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float
const auto &br = symbol.br;
const auto &tex = symbol.tex;
- float minZoom =
- util::max(static_cast<float>(zoom + log(symbol.minScale) / log(2)), placementZoom);
- float maxZoom = util::min(static_cast<float>(zoom + log(symbol.maxScale) / log(2)), 25.0f);
+ float minZoom = util::max(zoom + util::log2(symbol.minScale), placementZoom);
+ float maxZoom = util::min(zoom + util::log2(symbol.maxScale), util::MAX_ZOOM_F);
const auto &anchorPoint = symbol.anchorPoint;
// drop upside down versions of glyphs
@@ -449,41 +473,35 @@ void SymbolLayout::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float
minZoom = 0;
}
- const int glyph_vertex_length = 4;
-
- if (buffer.groups.empty() || buffer.groups.back().vertexLength + glyph_vertex_length > 65535) {
- // Move to a new group because the old one can't hold the geometry.
- buffer.groups.emplace_back();
+ if (buffer.segments.empty() || buffer.segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
+ buffer.segments.emplace_back(buffer.vertices.vertexSize(), buffer.triangles.indexSize());
}
// We're generating triangle fans, so we always start with the first
// coordinate in this polygon.
- auto& group = buffer.groups.back();
- size_t index = group.vertexLength;
+ auto& segment = buffer.segments.back();
+ assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
+ uint16_t index = segment.vertexLength;
// Encode angle of glyph
uint8_t glyphAngle = std::round((symbol.glyphAngle / (M_PI * 2)) * 256);
// coordinates (2 triangles)
- buffer.vertices.emplace_back(anchorPoint.x, anchorPoint.y, tl.x, tl.y, tex.x, tex.y, minZoom,
- maxZoom, placementZoom, glyphAngle);
- buffer.vertices.emplace_back(anchorPoint.x, anchorPoint.y, tr.x, tr.y, tex.x + tex.w, tex.y,
- minZoom, maxZoom, placementZoom, glyphAngle);
- buffer.vertices.emplace_back(anchorPoint.x, anchorPoint.y, bl.x, bl.y, tex.x, tex.y + tex.h,
- minZoom, maxZoom, placementZoom, glyphAngle);
- buffer.vertices.emplace_back(anchorPoint.x, anchorPoint.y, br.x, br.y, tex.x + tex.w, tex.y + tex.h,
- minZoom, maxZoom, placementZoom, glyphAngle);
+ buffer.vertices.emplace_back(SymbolAttributes::vertex(anchorPoint, tl, tex.x, tex.y,
+ minZoom, maxZoom, placementZoom, glyphAngle));
+ buffer.vertices.emplace_back(SymbolAttributes::vertex(anchorPoint, tr, tex.x + tex.w, tex.y,
+ minZoom, maxZoom, placementZoom, glyphAngle));
+ buffer.vertices.emplace_back(SymbolAttributes::vertex(anchorPoint, bl, tex.x, tex.y + tex.h,
+ minZoom, maxZoom, placementZoom, glyphAngle));
+ buffer.vertices.emplace_back(SymbolAttributes::vertex(anchorPoint, br, tex.x + tex.w, tex.y + tex.h,
+ minZoom, maxZoom, placementZoom, glyphAngle));
// add the two triangles, referencing the four coordinates we just inserted.
- buffer.triangles.emplace_back(static_cast<uint16_t>(index + 0),
- static_cast<uint16_t>(index + 1),
- static_cast<uint16_t>(index + 2));
- buffer.triangles.emplace_back(static_cast<uint16_t>(index + 1),
- static_cast<uint16_t>(index + 2),
- static_cast<uint16_t>(index + 3));
-
- group.vertexLength += glyph_vertex_length;
- group.indexLength += 2;
+ buffer.triangles.emplace_back(index + 0, index + 1, index + 2);
+ buffer.triangles.emplace_back(index + 1, index + 2, index + 3);
+
+ segment.vertexLength += vertexLength;
+ segment.indexLength += 6;
}
}
@@ -496,10 +514,6 @@ void SymbolLayout::addToDebugBuffers(CollisionTile& collisionTile, SymbolBucket&
const float yStretch = collisionTile.yStretch;
auto& collisionBox = bucket.collisionBox;
- if (collisionBox.groups.empty()) {
- // Move to a new group because the old one can't hold the geometry.
- collisionBox.groups.emplace_back();
- }
for (const SymbolInstance &symbolInstance : symbolInstances) {
auto populateCollisionBox = [&](const auto& feature) {
@@ -515,20 +529,31 @@ void SymbolLayout::addToDebugBuffers(CollisionTile& collisionTile, SymbolBucket&
bl = util::matrixMultiply(collisionTile.reverseRotationMatrix, bl);
br = util::matrixMultiply(collisionTile.reverseRotationMatrix, br);
- const float maxZoom = util::clamp(zoom + log(box.maxScale) / log(2), util::MIN_ZOOM, util::MAX_ZOOM);
- const float placementZoom = util::clamp(zoom + log(box.placementScale) / log(2), util::MIN_ZOOM, util::MAX_ZOOM);
+ const float maxZoom = util::clamp(zoom + util::log2(box.maxScale), util::MIN_ZOOM_F, util::MAX_ZOOM_F);
+ const float placementZoom = util::clamp(zoom + util::log2(box.placementScale), util::MIN_ZOOM_F, util::MAX_ZOOM_F);
+
+ static constexpr std::size_t vertexLength = 4;
+ static constexpr std::size_t indexLength = 8;
+
+ if (collisionBox.segments.empty() || collisionBox.segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
+ collisionBox.segments.emplace_back(collisionBox.vertices.vertexSize(), collisionBox.lines.indexSize());
+ }
+
+ auto& segment = collisionBox.segments.back();
+ uint16_t index = segment.vertexLength;
+
+ collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, tl, maxZoom, placementZoom));
+ collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, tr, maxZoom, placementZoom));
+ collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, br, maxZoom, placementZoom));
+ collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, bl, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(anchor.x, anchor.y, tl.x, tl.y, maxZoom, placementZoom);
- collisionBox.vertices.emplace_back(anchor.x, anchor.y, tr.x, tr.y, maxZoom, placementZoom);
- collisionBox.vertices.emplace_back(anchor.x, anchor.y, tr.x, tr.y, maxZoom, placementZoom);
- collisionBox.vertices.emplace_back(anchor.x, anchor.y, br.x, br.y, maxZoom, placementZoom);
- collisionBox.vertices.emplace_back(anchor.x, anchor.y, br.x, br.y, maxZoom, placementZoom);
- collisionBox.vertices.emplace_back(anchor.x, anchor.y, bl.x, bl.y, maxZoom, placementZoom);
- collisionBox.vertices.emplace_back(anchor.x, anchor.y, bl.x, bl.y, maxZoom, placementZoom);
- collisionBox.vertices.emplace_back(anchor.x, anchor.y, tl.x, tl.y, maxZoom, placementZoom);
+ collisionBox.lines.emplace_back(index + 0, index + 1);
+ collisionBox.lines.emplace_back(index + 1, index + 2);
+ collisionBox.lines.emplace_back(index + 2, index + 3);
+ collisionBox.lines.emplace_back(index + 3, index + 0);
- auto& group = collisionBox.groups.back();
- group.vertexLength += 8;
+ segment.vertexLength += vertexLength;
+ segment.indexLength += indexLength;
}
};
populateCollisionBox(symbolInstance.textCollisionFeature);
diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp
index 54acf84aaf..c89b791ccc 100644
--- a/src/mbgl/layout/symbol_layout.hpp
+++ b/src/mbgl/layout/symbol_layout.hpp
@@ -4,6 +4,7 @@
#include <mbgl/style/layers/symbol_layer_properties.hpp>
#include <mbgl/layout/symbol_feature.hpp>
#include <mbgl/layout/symbol_instance.hpp>
+#include <mbgl/text/bidi.hpp>
#include <memory>
#include <map>
@@ -20,20 +21,21 @@ class SymbolBucket;
namespace style {
class Filter;
+class Layer;
} // namespace style
struct Anchor;
class SymbolLayout {
public:
- SymbolLayout(std::string bucketName_,
+ SymbolLayout(std::vector<std::string> layerIDs_,
std::string sourceLayerName_,
uint32_t overscaling,
float zoom,
const MapMode,
const GeometryTileLayer&,
const style::Filter&,
- style::SymbolLayoutProperties,
+ style::SymbolLayoutProperties::Evaluated,
float textMaxSize,
SpriteAtlas&);
@@ -54,18 +56,17 @@ public:
State state = Pending;
- const std::string bucketName;
+ const std::vector<std::string> layerIDs;
const std::string sourceLayerName;
private:
- void addFeature(const GeometryCollection&,
+ void addFeature(const SymbolFeature&,
const Shaping& shapedText,
const PositionedIcon& shapedIcon,
- const GlyphPositions& face,
- const size_t index);
+ const GlyphPositions& face);
- bool anchorIsTooClose(const std::u32string& text, const float repeatDistance, Anchor&);
- std::map<std::u32string, std::vector<Anchor>> compareText;
+ bool anchorIsTooClose(const std::u16string& text, const float repeatDistance, const Anchor&);
+ std::map<std::u16string, std::vector<Anchor>> compareText;
void addToDebugBuffers(CollisionTile&, SymbolBucket&);
@@ -77,7 +78,7 @@ private:
const float overscaling;
const float zoom;
const MapMode mode;
- const style::SymbolLayoutProperties layout;
+ const style::SymbolLayoutProperties::Evaluated layout;
const float textMaxSize;
SpriteAtlas& spriteAtlas;
@@ -91,6 +92,8 @@ private:
GlyphRangeSet ranges;
std::vector<SymbolInstance> symbolInstances;
std::vector<SymbolFeature> features;
+
+ BiDi bidi; // Consider moving this up to geometry tile worker to reduce reinstantiation costs; use of BiDi/ubiditransform object must be constrained to one thread
};
} // namespace mbgl
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index 1efc1c063a..e9d4d9e247 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -23,7 +23,8 @@
#include <mbgl/util/mapbox.hpp>
#include <mbgl/util/tile_coordinate.hpp>
#include <mbgl/actor/scheduler.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
+#include <mbgl/math/log2.hpp>
namespace mbgl {
@@ -46,7 +47,8 @@ struct StillImageRequest {
class Map::Impl : public style::Observer {
public:
- Impl(Backend&,
+ Impl(Map&,
+ Backend&,
float pixelRatio,
FileSource&,
Scheduler&,
@@ -61,11 +63,12 @@ public:
void onStyleError() override;
void onResourceError(std::exception_ptr) override;
- void update();
void render(View&);
+ void renderStill();
void loadStyleJSON(const std::string&);
+ Map& map;
Backend& backend;
FileSource& fileSource;
Scheduler& scheduler;
@@ -80,7 +83,6 @@ public:
MapDebugOptions debugOptions { MapDebugOptions::NoDebug };
Update updateFlags = Update::Nothing;
- util::AsyncTask asyncUpdate;
std::unique_ptr<AnnotationManager> annotationManager;
std::unique_ptr<Painter> painter;
@@ -89,17 +91,19 @@ public:
std::string styleURL;
std::string styleJSON;
bool styleMutated = false;
+ bool cameraMutated = false;
std::unique_ptr<AsyncRequest> styleRequest;
- std::unique_ptr<StillImageRequest> stillImageRequest;
size_t sourceCacheSize;
- TimePoint timePoint;
bool loading = false;
+
+ util::AsyncTask asyncInvalidate;
+ std::unique_ptr<StillImageRequest> stillImageRequest;
};
Map::Map(Backend& backend,
- const std::array<uint16_t, 2> size,
+ const Size size,
const float pixelRatio,
FileSource& fileSource,
Scheduler& scheduler,
@@ -107,7 +111,8 @@ Map::Map(Backend& backend,
GLContextMode contextMode,
ConstrainMode constrainMode,
ViewportMode viewportMode)
- : impl(std::make_unique<Impl>(backend,
+ : impl(std::make_unique<Impl>(*this,
+ backend,
pixelRatio,
fileSource,
scheduler,
@@ -118,7 +123,8 @@ Map::Map(Backend& backend,
impl->transform.resize(size);
}
-Map::Impl::Impl(Backend& backend_,
+Map::Impl::Impl(Map& map_,
+ Backend& backend_,
float pixelRatio_,
FileSource& fileSource_,
Scheduler& scheduler_,
@@ -126,7 +132,8 @@ Map::Impl::Impl(Backend& backend_,
GLContextMode contextMode_,
ConstrainMode constrainMode_,
ViewportMode viewportMode_)
- : backend(backend_),
+ : map(map_),
+ backend(backend_),
fileSource(fileSource_),
scheduler(scheduler_),
transform([this](MapChange change) { backend.notifyMapChange(change); },
@@ -135,8 +142,14 @@ Map::Impl::Impl(Backend& backend_,
mode(mode_),
contextMode(contextMode_),
pixelRatio(pixelRatio_),
- asyncUpdate([this] { update(); }),
- annotationManager(std::make_unique<AnnotationManager>(pixelRatio)) {
+ annotationManager(std::make_unique<AnnotationManager>(pixelRatio)),
+ asyncInvalidate([this] {
+ if (mode == MapMode::Continuous) {
+ backend.invalidate();
+ } else {
+ renderStill();
+ }
+ }) {
}
Map::~Map() {
@@ -178,64 +191,37 @@ void Map::renderStill(View& view, StillImageCallback callback) {
}
impl->stillImageRequest = std::make_unique<StillImageRequest>(view, std::move(callback));
- impl->updateFlags |= Update::RenderStill;
- impl->asyncUpdate.send();
+ impl->onUpdate(Update::Repaint);
}
-void Map::render(View& view) {
- if (!impl->style) {
+void Map::Impl::renderStill() {
+ if (!stillImageRequest) {
return;
}
- if (impl->renderState == RenderState::Never) {
- impl->backend.notifyMapChange(MapChangeWillStartRenderingMap);
- }
-
- impl->backend.notifyMapChange(MapChangeWillStartRenderingFrame);
-
- const Update flags = impl->transform.updateTransitions(Clock::now());
-
- impl->render(view);
-
- impl->backend.notifyMapChange(isFullyLoaded() ?
- MapChangeDidFinishRenderingFrameFullyRendered :
- MapChangeDidFinishRenderingFrame);
-
- if (!isFullyLoaded()) {
- impl->renderState = RenderState::Partial;
- } else if (impl->renderState != RenderState::Fully) {
- impl->renderState = RenderState::Fully;
- impl->backend.notifyMapChange(MapChangeDidFinishRenderingMapFullyRendered);
- if (impl->loading) {
- impl->loading = false;
- impl->backend.notifyMapChange(MapChangeDidFinishLoadingMap);
- }
- }
-
- // Triggers an asynchronous update, that eventually triggers a view
- // invalidation, causing renderSync to be called again if in transition.
- if (flags != Update::Nothing) {
- impl->onUpdate(flags);
- }
+ // TODO: determine whether we need activate/deactivate
+ BackendScope guard(backend);
+ render(stillImageRequest->view);
}
void Map::triggerRepaint() {
impl->backend.invalidate();
}
-void Map::Impl::update() {
- if (!style) {
- updateFlags = Update::Nothing;
- }
+void Map::render(View& view) {
+ impl->render(view);
+}
- if (updateFlags == Update::Nothing || (mode == MapMode::Still && !stillImageRequest)) {
+void Map::Impl::render(View& view) {
+ if (!style) {
return;
}
- // This time point is used to:
- // - Calculate style property transitions;
- // - Hint style sources to notify when all its tiles are loaded;
- timePoint = Clock::now();
+ TimePoint timePoint = Clock::now();
+
+ auto flags = transform.updateTransitions(timePoint);
+
+ updateFlags |= flags;
if (style->loaded && updateFlags & Update::AnnotationStyle) {
annotationManager->updateStyle(*style);
@@ -269,46 +255,74 @@ void Map::Impl::update() {
style->updateTiles(parameters);
- if (mode == MapMode::Continuous) {
- backend.invalidate();
- } else if (stillImageRequest && style->isLoaded()) {
- // TODO: determine whether we need activate/deactivate
- BackendScope guard(backend);
- render(stillImageRequest->view);
- }
-
updateFlags = Update::Nothing;
-}
-void Map::Impl::render(View& view) {
if (!painter) {
- painter = std::make_unique<Painter>(backend.getContext(), transform.getState());
+ painter = std::make_unique<Painter>(backend.getContext(), transform.getState(), pixelRatio);
}
- FrameData frameData { timePoint,
- pixelRatio,
- mode,
- contextMode,
- debugOptions };
+ if (mode == MapMode::Continuous) {
+ if (renderState == RenderState::Never) {
+ backend.notifyMapChange(MapChangeWillStartRenderingMap);
+ }
+
+ backend.notifyMapChange(MapChangeWillStartRenderingFrame);
+
+ FrameData frameData { timePoint,
+ pixelRatio,
+ mode,
+ contextMode,
+ debugOptions };
+
+ painter->render(*style,
+ frameData,
+ view,
+ annotationManager->getSpriteAtlas());
+
+ painter->cleanup();
+
+ backend.notifyMapChange(style->isLoaded() ?
+ MapChangeDidFinishRenderingFrameFullyRendered :
+ MapChangeDidFinishRenderingFrame);
+
+ if (!style->isLoaded()) {
+ renderState = RenderState::Partial;
+ } else if (renderState != RenderState::Fully) {
+ renderState = RenderState::Fully;
+ backend.notifyMapChange(MapChangeDidFinishRenderingMapFullyRendered);
+ if (loading) {
+ loading = false;
+ backend.notifyMapChange(MapChangeDidFinishLoadingMap);
+ }
+ }
- painter->render(*style,
- frameData,
- view,
- annotationManager->getSpriteAtlas());
+ if (style->hasTransitions()) {
+ flags |= Update::RecalculateStyle;
+ } else if (painter->needsAnimation()) {
+ flags |= Update::Repaint;
+ }
+
+ // Only schedule an update if we need to paint another frame due to transitions or
+ // animations that are still in progress
+ if (flags != Update::Nothing) {
+ onUpdate(flags);
+ }
+ } else if (stillImageRequest && style->isLoaded()) {
+ FrameData frameData { timePoint,
+ pixelRatio,
+ mode,
+ contextMode,
+ debugOptions };
+
+ painter->render(*style,
+ frameData,
+ view,
+ annotationManager->getSpriteAtlas());
- if (mode == MapMode::Still) {
auto request = std::move(stillImageRequest);
request->callback(nullptr);
- }
-
- painter->cleanup();
- if (style->hasTransitions()) {
- updateFlags |= Update::RecalculateStyle;
- asyncUpdate.send();
- } else if (painter->needsAnimation()) {
- updateFlags |= Update::Repaint;
- asyncUpdate.send();
+ painter->cleanup();
}
}
@@ -384,8 +398,15 @@ void Map::Impl::loadStyleJSON(const std::string& json) {
// force style cascade, causing all pending transitions to complete.
style->cascade(Clock::now(), mode);
- updateFlags |= Update::Classes | Update::RecalculateStyle | Update::AnnotationStyle;
- asyncUpdate.send();
+ if (!cameraMutated) {
+ // Zoom first because it may constrain subsequent operations.
+ map.setZoom(map.getDefaultZoom());
+ map.setLatLng(map.getDefaultLatLng());
+ map.setBearing(map.getDefaultBearing());
+ map.setPitch(map.getDefaultPitch());
+ }
+
+ onUpdate(Update::Classes | Update::RecalculateStyle | Update::AnnotationStyle);
}
std::string Map::getStyleURL() const {
@@ -431,16 +452,19 @@ CameraOptions Map::getCameraOptions(optional<EdgeInsets> padding) const {
}
void Map::jumpTo(const CameraOptions& camera) {
+ impl->cameraMutated = true;
impl->transform.jumpTo(camera);
impl->onUpdate(camera.zoom ? Update::RecalculateStyle : Update::Repaint);
}
void Map::easeTo(const CameraOptions& camera, const AnimationOptions& animation) {
+ impl->cameraMutated = true;
impl->transform.easeTo(camera, animation);
impl->onUpdate(camera.zoom ? Update::RecalculateStyle : Update::Repaint);
}
void Map::flyTo(const CameraOptions& camera, const AnimationOptions& animation) {
+ impl->cameraMutated = true;
impl->transform.flyTo(camera, animation);
impl->onUpdate(Update::RecalculateStyle);
}
@@ -448,20 +472,24 @@ void Map::flyTo(const CameraOptions& camera, const AnimationOptions& animation)
#pragma mark - Position
void Map::moveBy(const ScreenCoordinate& point, const Duration& duration) {
+ impl->cameraMutated = true;
impl->transform.moveBy(point, duration);
impl->onUpdate(Update::Repaint);
}
void Map::setLatLng(const LatLng& latLng, const Duration& duration) {
+ impl->cameraMutated = true;
setLatLng(latLng, optional<ScreenCoordinate> {}, duration);
}
void Map::setLatLng(const LatLng& latLng, optional<EdgeInsets> padding, const Duration& duration) {
+ impl->cameraMutated = true;
impl->transform.setLatLng(latLng, padding, duration);
impl->onUpdate(Update::Repaint);
}
void Map::setLatLng(const LatLng& latLng, optional<ScreenCoordinate> anchor, const Duration& duration) {
+ impl->cameraMutated = true;
impl->transform.setLatLng(latLng, anchor, duration);
impl->onUpdate(Update::Repaint);
}
@@ -471,6 +499,7 @@ LatLng Map::getLatLng(optional<EdgeInsets> padding) const {
}
void Map::resetPosition(optional<EdgeInsets> padding) {
+ impl->cameraMutated = true;
CameraOptions camera;
camera.angle = 0;
camera.pitch = 0;
@@ -485,11 +514,13 @@ void Map::resetPosition(optional<EdgeInsets> padding) {
#pragma mark - Scale
void Map::scaleBy(double ds, optional<ScreenCoordinate> anchor, const Duration& duration) {
+ impl->cameraMutated = true;
impl->transform.scaleBy(ds, anchor, duration);
impl->onUpdate(Update::RecalculateStyle);
}
void Map::setScale(double scale, optional<ScreenCoordinate> anchor, const Duration& duration) {
+ impl->cameraMutated = true;
impl->transform.setScale(scale, anchor, duration);
impl->onUpdate(Update::RecalculateStyle);
}
@@ -499,10 +530,12 @@ double Map::getScale() const {
}
void Map::setZoom(double zoom, const Duration& duration) {
+ impl->cameraMutated = true;
setZoom(zoom, {}, duration);
}
void Map::setZoom(double zoom, optional<EdgeInsets> padding, const Duration& duration) {
+ impl->cameraMutated = true;
impl->transform.setZoom(zoom, padding, duration);
impl->onUpdate(Update::RecalculateStyle);
}
@@ -512,10 +545,12 @@ double Map::getZoom() const {
}
void Map::setLatLngZoom(const LatLng& latLng, double zoom, const Duration& duration) {
+ impl->cameraMutated = true;
setLatLngZoom(latLng, zoom, {}, duration);
}
void Map::setLatLngZoom(const LatLng& latLng, double zoom, optional<EdgeInsets> padding, const Duration& duration) {
+ impl->cameraMutated = true;
impl->transform.setLatLngZoom(latLng, zoom, padding, duration);
impl->onUpdate(Update::RecalculateStyle);
}
@@ -538,7 +573,7 @@ CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, optional
// Calculate the bounds of the possibly rotated shape with respect to the viewport.
ScreenCoordinate nePixel = {-INFINITY, -INFINITY};
ScreenCoordinate swPixel = {INFINITY, INFINITY};
- double viewportHeight = getHeight();
+ double viewportHeight = getSize().height;
for (LatLng latLng : latLngs) {
ScreenCoordinate pixel = pixelForLatLng(latLng);
swPixel.x = std::min(swPixel.x, pixel.x);
@@ -552,8 +587,8 @@ CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, optional
// Calculate the zoom level.
double minScale = INFINITY;
if (width > 0 || height > 0) {
- double scaleX = getWidth() / width;
- double scaleY = getHeight() / height;
+ double scaleX = double(getSize().width) / width;
+ double scaleY = double(getSize().height) / height;
if (padding && *padding) {
scaleX -= (padding->left + padding->right) / width;
scaleY -= (padding->top + padding->bottom) / height;
@@ -587,6 +622,7 @@ CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, optional
}
void Map::resetZoom() {
+ impl->cameraMutated = true;
setZoom(0);
}
@@ -614,36 +650,36 @@ double Map::getMaxZoom() const {
#pragma mark - Size
-void Map::setSize(const std::array<uint16_t, 2>& size) {
+void Map::setSize(const Size size) {
impl->transform.resize(size);
impl->onUpdate(Update::Repaint);
}
-uint16_t Map::getWidth() const {
- return impl->transform.getState().getWidth();
-}
-
-uint16_t Map::getHeight() const {
- return impl->transform.getState().getHeight();
+Size Map::getSize() const {
+ return impl->transform.getState().getSize();
}
#pragma mark - Rotation
void Map::rotateBy(const ScreenCoordinate& first, const ScreenCoordinate& second, const Duration& duration) {
+ impl->cameraMutated = true;
impl->transform.rotateBy(first, second, duration);
impl->onUpdate(Update::Repaint);
}
void Map::setBearing(double degrees, const Duration& duration) {
+ impl->cameraMutated = true;
setBearing(degrees, EdgeInsets(), duration);
}
void Map::setBearing(double degrees, optional<ScreenCoordinate> anchor, const Duration& duration) {
+ impl->cameraMutated = true;
impl->transform.setAngle(-degrees * util::DEG2RAD, anchor, duration);
impl->onUpdate(Update::Repaint);
}
void Map::setBearing(double degrees, optional<EdgeInsets> padding, const Duration& duration) {
+ impl->cameraMutated = true;
impl->transform.setAngle(-degrees * util::DEG2RAD, padding, duration);
impl->onUpdate(Update::Repaint);
}
@@ -653,6 +689,7 @@ double Map::getBearing() const {
}
void Map::resetNorth(const Duration& duration) {
+ impl->cameraMutated = true;
impl->transform.setAngle(0, duration);
impl->onUpdate(Update::Repaint);
}
@@ -660,10 +697,12 @@ void Map::resetNorth(const Duration& duration) {
#pragma mark - Pitch
void Map::setPitch(double pitch, const Duration& duration) {
+ impl->cameraMutated = true;
setPitch(pitch, {}, duration);
}
void Map::setPitch(double pitch, optional<ScreenCoordinate> anchor, const Duration& duration) {
+ impl->cameraMutated = true;
impl->transform.setPitch(pitch * util::DEG2RAD, anchor, duration);
impl->onUpdate(Update::Repaint);
}
@@ -789,7 +828,8 @@ AnnotationIDs Map::queryPointAnnotations(const ScreenBox& box) {
std::set<AnnotationID> set;
for (auto &feature : features) {
assert(feature.id);
- assert(*feature.id <= std::numeric_limits<AnnotationID>::max());
+ assert(feature.id->is<uint64_t>());
+ assert(feature.id->get<uint64_t>() <= std::numeric_limits<AnnotationID>::max());
set.insert(static_cast<AnnotationID>(feature.id->get<uint64_t>()));
}
AnnotationIDs ids;
@@ -826,7 +866,7 @@ std::unique_ptr<Source> Map::removeSource(const std::string& sourceID) {
}
return nullptr;
}
-
+
std::vector<style::Layer*> Map::getLayers() {
return impl->style ? impl->style->getLayers() : std::vector<style::Layer*>();
}
@@ -1041,9 +1081,9 @@ void Map::Impl::onSourceAttributionChanged(style::Source&, const std::string&) {
void Map::Impl::onUpdate(Update flags) {
updateFlags |= flags;
- asyncUpdate.send();
+ asyncInvalidate.send();
}
-
+
void Map::Impl::onStyleLoaded() {
backend.notifyMapChange(MapChangeDidFinishLoadingStyle);
}
diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp
index 85805a109d..ba5e205301 100644
--- a/src/mbgl/map/transform.cpp
+++ b/src/mbgl/map/transform.cpp
@@ -9,8 +9,8 @@
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/projection.hpp>
#include <mbgl/math/clamp.hpp>
-#include <mbgl/platform/log.hpp>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/logging.hpp>
+#include <mbgl/util/platform.hpp>
#include <cstdio>
#include <cmath>
@@ -45,8 +45,8 @@ Transform::Transform(std::function<void(MapChange)> callback_,
#pragma mark - Map View
-bool Transform::resize(const std::array<uint16_t, 2> size) {
- if (state.width == size[0] && state.height == size[1]) {
+bool Transform::resize(const Size size) {
+ if (state.size == size) {
return false;
}
@@ -54,8 +54,7 @@ bool Transform::resize(const std::array<uint16_t, 2> size) {
callback(MapChangeRegionWillChange);
}
- state.width = size[0];
- state.height = size[1];
+ state.size = size;
state.constrain(state.scale, state.x, state.y);
if (callback) {
@@ -117,7 +116,7 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim
const Point<double> endPoint = Projection::project(latLng, state.scale);
ScreenCoordinate center = getScreenCoordinate(padding);
- center.y = state.height - center.y;
+ center.y = state.size.height - center.y;
// Constrain camera options.
zoom = util::clamp(zoom, state.getMinZoom(), state.getMaxZoom());
@@ -187,7 +186,7 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
const Point<double> endPoint = Projection::project(latLng, state.scale);
ScreenCoordinate center = getScreenCoordinate(padding);
- center.y = state.height - center.y;
+ center.y = state.size.height - center.y;
// Constrain camera options.
zoom = util::clamp(zoom, state.getMinZoom(), state.getMaxZoom());
@@ -203,9 +202,9 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
/// w₀: Initial visible span, measured in pixels at the initial scale.
/// Known henceforth as a <i>screenful</i>.
- double w0 = padding ? std::max(state.width, state.height)
- : std::max(state.width - padding.left - padding.right,
- state.height - padding.top - padding.bottom);
+ double w0 = padding ? std::max(state.size.width, state.size.height)
+ : std::max(state.size.width - padding.left - padding.right,
+ state.size.height - padding.top - padding.bottom);
/// w₁: Final visible span, measured in pixels with respect to the initial
/// scale.
double w1 = w0 / state.zoomScale(zoom - startZoom);
@@ -355,8 +354,8 @@ void Transform::setLatLng(const LatLng& latLng, optional<ScreenCoordinate> ancho
EdgeInsets padding;
padding.top = anchor->y;
padding.left = anchor->x;
- padding.bottom = state.height - anchor->y;
- padding.right = state.width - anchor->x;
+ padding.bottom = state.size.height - anchor->y;
+ padding.right = state.size.width - anchor->x;
if (padding) camera.padding = padding;
}
easeTo(camera, duration);
@@ -378,7 +377,7 @@ void Transform::setLatLngZoom(const LatLng& latLng, double zoom, optional<EdgeIn
LatLng Transform::getLatLng(optional<EdgeInsets> padding) const {
if (padding && *padding) {
- return screenCoordinateToLatLng(padding->getCenter(state.width, state.height));
+ return screenCoordinateToLatLng(padding->getCenter(state.size.width, state.size.height));
} else {
return state.getLatLng();
}
@@ -386,9 +385,9 @@ LatLng Transform::getLatLng(optional<EdgeInsets> padding) const {
ScreenCoordinate Transform::getScreenCoordinate(optional<EdgeInsets> padding) const {
if (padding && *padding) {
- return padding->getCenter(state.width, state.height);
+ return padding->getCenter(state.size.width, state.size.height);
} else {
- return { state.width / 2., state.height / 2. };
+ return { state.size.width / 2., state.size.height / 2. };
}
}
@@ -565,7 +564,7 @@ void Transform::startTransition(const CameraOptions& camera,
optional<ScreenCoordinate> anchor = camera.anchor;
LatLng anchorLatLng;
if (anchor) {
- anchor->y = state.getHeight() - anchor->y;
+ anchor->y = state.size.height - anchor->y;
anchorLatLng = state.screenCoordinateToLatLng(*anchor);
}
@@ -650,13 +649,13 @@ ScreenCoordinate Transform::latLngToScreenCoordinate(const LatLng& latLng) const
LatLng unwrappedLatLng = latLng.wrapped();
unwrappedLatLng.unwrapForShortestPath(getLatLng());
ScreenCoordinate point = state.latLngToScreenCoordinate(unwrappedLatLng);
- point.y = state.height - point.y;
+ point.y = state.size.height - point.y;
return point;
}
LatLng Transform::screenCoordinateToLatLng(const ScreenCoordinate& point) const {
ScreenCoordinate flippedPoint = point;
- flippedPoint.y = state.height - flippedPoint.y;
+ flippedPoint.y = state.size.height - flippedPoint.y;
return state.screenCoordinateToLatLng(flippedPoint).wrapped();
}
diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp
index abc301b1cb..febe71035d 100644
--- a/src/mbgl/map/transform.hpp
+++ b/src/mbgl/map/transform.hpp
@@ -23,7 +23,7 @@ public:
ViewportMode = ViewportMode::Default);
// Map view
- bool resize(std::array<uint16_t, 2> size);
+ bool resize(Size size);
// Camera
/** Returns the current camera options. */
diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp
index 4f6bcecdb6..f7419fa5b4 100644
--- a/src/mbgl/map/transform_state.cpp
+++ b/src/mbgl/map/transform_state.cpp
@@ -2,7 +2,7 @@
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/interpolate.hpp>
-#include <mbgl/util/math.hpp>
+#include <mbgl/math/log2.hpp>
#include <mbgl/math/clamp.hpp>
namespace mbgl {
@@ -27,21 +27,27 @@ void TransformState::matrixFor(mat4& matrix, const UnwrappedTileID& tileID) cons
}
void TransformState::getProjMatrix(mat4& projMatrix) const {
- double halfFov = std::atan(0.5 / getAltitude());
- double topHalfSurfaceDistance = std::sin(halfFov) * getAltitude() /
- std::sin(M_PI / 2.0f - getPitch() - halfFov);
- // Calculate z value of the farthest fragment that should be rendered.
- double farZ = std::cos(M_PI / 2.0f - getPitch()) * topHalfSurfaceDistance + getAltitude();
- matrix::perspective(projMatrix, 2.0f * std::atan((getHeight() / 2.0f) / getAltitude()),
- double(getWidth()) / getHeight(), 0.1, farZ);
+ // Find the distance from the center point [width/2, height/2] to the
+ // center top point [width/2, 0] in Z units, using the law of sines.
+ // 1 Z unit is equivalent to 1 horizontal px at the center of the map
+ // (the distance between[width/2, height/2] and [width/2 + 1, height/2])
+ const double halfFov = getFieldOfView() / 2.0;
+ const double groundAngle = M_PI / 2.0 + getPitch();
+ const double topHalfSurfaceDistance = std::sin(halfFov) * getCameraToCenterDistance() / std::sin(M_PI - groundAngle - halfFov);
- matrix::translate(projMatrix, projMatrix, 0, 0, -getAltitude());
- // After the rotateX, z values are in pixel units. Convert them to
- // altitude unites. 1 altitude unit = the screen height.
+ // Calculate z distance of the farthest fragment that should be rendered.
+ const double furthestDistance = std::cos(M_PI / 2 - getPitch()) * topHalfSurfaceDistance + getCameraToCenterDistance();
+ // Add a bit extra to avoid precision problems when a fragment's distance is exactly `furthestDistance`
+ const double farZ = furthestDistance * 1.01;
+
+ matrix::perspective(projMatrix, getFieldOfView(), double(size.width) / size.height, 1, farZ);
+
const bool flippedY = viewportMode == ViewportMode::FlippedY;
- matrix::scale(projMatrix, projMatrix, 1, flippedY ? 1 : -1, 1.0f / (rotatedNorth() ? getWidth() : getHeight()));
+ matrix::scale(projMatrix, projMatrix, 1, flippedY ? 1 : -1, 1);
+
+ matrix::translate(projMatrix, projMatrix, 0, 0, -getCameraToCenterDistance());
using NO = NorthOrientation;
switch (getNorthOrientation()) {
@@ -53,18 +59,14 @@ void TransformState::getProjMatrix(mat4& projMatrix) const {
matrix::rotate_z(projMatrix, projMatrix, getAngle() + getNorthOrientationAngle());
- matrix::translate(projMatrix, projMatrix, pixel_x() - getWidth() / 2.0f,
- pixel_y() - getHeight() / 2.0f, 0);
+ matrix::translate(projMatrix, projMatrix, pixel_x() - size.width / 2.0f,
+ pixel_y() - size.height / 2.0f, 0);
}
#pragma mark - Dimensions
-uint16_t TransformState::getWidth() const {
- return width;
-}
-
-uint16_t TransformState::getHeight() const {
- return height;
+Size TransformState::getSize() const {
+ return size;
}
#pragma mark - North Orientation
@@ -108,23 +110,23 @@ LatLng TransformState::getLatLng(LatLng::WrapMode wrapMode) const {
}
double TransformState::pixel_x() const {
- const double center = (width - Projection::worldSize(scale)) / 2;
+ const double center = (size.width - Projection::worldSize(scale)) / 2;
return center + x;
}
double TransformState::pixel_y() const {
- const double center = (height - Projection::worldSize(scale)) / 2;
+ const double center = (size.height - Projection::worldSize(scale)) / 2;
return center + y;
}
#pragma mark - Zoom
double TransformState::getZoom() const {
- return std::log(scale) / M_LN2;
+ return scaleZoom(scale);
}
int32_t TransformState::getIntegerZoom() const {
- return std::floor(getZoom());
+ return getZoom();
}
double TransformState::getZoomFraction() const {
@@ -167,8 +169,12 @@ float TransformState::getAngle() const {
return angle;
}
-float TransformState::getAltitude() const {
- return altitude;
+float TransformState::getFieldOfView() const {
+ return fov;
+}
+
+float TransformState::getCameraToCenterDistance() const {
+ return 0.5 * size.height / std::tan(fov / 2.0);
}
float TransformState::getPitch() const {
@@ -202,7 +208,7 @@ bool TransformState::isGestureInProgress() const {
#pragma mark - Projection
double TransformState::zoomScale(double zoom) const {
- return std::pow(2.0f, zoom);
+ return std::pow(2.0, zoom);
}
double TransformState::scaleZoom(double s) const {
@@ -210,7 +216,7 @@ double TransformState::scaleZoom(double s) const {
}
ScreenCoordinate TransformState::latLngToScreenCoordinate(const LatLng& latLng) const {
- if (width == 0 || height == 0) {
+ if (!size) {
return {};
}
@@ -219,11 +225,11 @@ ScreenCoordinate TransformState::latLngToScreenCoordinate(const LatLng& latLng)
Point<double> pt = Projection::project(latLng, scale) / double(util::tileSize);
vec4 c = {{ pt.x, pt.y, 0, 1 }};
matrix::transformMat4(p, c, mat);
- return { p[0] / p[3], height - p[1] / p[3] };
+ return { p[0] / p[3], size.height - p[1] / p[3] };
}
LatLng TransformState::screenCoordinateToLatLng(const ScreenCoordinate& point, LatLng::WrapMode wrapMode) const {
- if (width == 0 || height == 0) {
+ if (!size) {
return {};
}
@@ -235,7 +241,7 @@ LatLng TransformState::screenCoordinateToLatLng(const ScreenCoordinate& point, L
if (err) throw std::runtime_error("failed to invert coordinatePointMatrix");
- double flippedY = height - point.y;
+ double flippedY = size.height - point.y;
// since we don't know the correct projected z value for the point,
// unproject two points to get a line and then find the point on that
@@ -273,7 +279,8 @@ mat4 TransformState::coordinatePointMatrix(double z) const {
mat4 TransformState::getPixelMatrix() const {
mat4 m;
matrix::identity(m);
- matrix::scale(m, m, width / 2.0f, -height / 2.0f, 1);
+ matrix::scale(m, m,
+ static_cast<double>(size.width) / 2, -static_cast<double>(size.height) / 2, 1);
matrix::translate(m, m, 1, -1, 0);
return m;
}
@@ -289,17 +296,17 @@ bool TransformState::rotatedNorth() const {
void TransformState::constrain(double& scale_, double& x_, double& y_) const {
// Constrain minimum scale to avoid zooming out far enough to show off-world areas.
scale_ = util::max(scale_,
- static_cast<double>((rotatedNorth() ? height : width) / util::tileSize),
- static_cast<double>((rotatedNorth() ? width : height) / util::tileSize));
+ static_cast<double>(rotatedNorth() ? size.height : size.width) / util::tileSize,
+ static_cast<double>(rotatedNorth() ? size.width : size.height) / util::tileSize);
// Constrain min/max pan to avoid showing off-world areas.
if (constrainMode == ConstrainMode::WidthAndHeight) {
- double max_x = (scale_ * util::tileSize - (rotatedNorth() ? height : width)) / 2;
+ double max_x = (scale_ * util::tileSize - (rotatedNorth() ? size.height : size.width)) / 2;
x_ = std::max(-max_x, std::min(x_, max_x));
}
if (constrainMode != ConstrainMode::None) {
- double max_y = (scale_ * util::tileSize - (rotatedNorth() ? width : height)) / 2;
+ double max_y = (scale_ * util::tileSize - (rotatedNorth() ? size.width : size.height)) / 2;
y_ = std::max(-max_y, std::min(y_, max_y));
}
}
diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp
index 8a12b62a9e..a35aa5a255 100644
--- a/src/mbgl/map/transform_state.hpp
+++ b/src/mbgl/map/transform_state.hpp
@@ -6,6 +6,7 @@
#include <mbgl/util/constants.hpp>
#include <mbgl/util/projection.hpp>
#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/size.hpp>
#include <cstdint>
#include <array>
@@ -26,8 +27,7 @@ public:
void getProjMatrix(mat4& matrix) const;
// Dimensions
- uint16_t getWidth() const;
- uint16_t getHeight() const;
+ Size getSize() const;
// North Orientation
NorthOrientation getNorthOrientation() const;
@@ -56,7 +56,8 @@ public:
// Rotation
float getAngle() const;
- float getAltitude() const;
+ float getFieldOfView() const;
+ float getCameraToCenterDistance() const;
float getPitch() const;
// State
@@ -84,7 +85,7 @@ private:
NorthOrientation orientation = NorthOrientation::Upwards;
// logical dimensions
- uint16_t width = 0, height = 0;
+ Size size;
mat4 coordinatePointMatrix(double z) const;
mat4 getPixelMatrix() const;
@@ -109,7 +110,11 @@ private:
double x = 0, y = 0;
double angle = 0;
double scale = 1;
- double altitude = 1.5;
+ // This fov value is somewhat arbitrary. The altitude of the camera used
+ // to be defined as 1.5 screen heights above the ground, which was an
+ // arbitrary choice. This is the fov equivalent to that value calculated with:
+ // `fov = 2 * arctan((height / 2) / (height * 1.5))`
+ double fov = 0.6435011087932844;
double pitch = 0.0;
// cache values for spherical mercator math
diff --git a/src/mbgl/map/update.hpp b/src/mbgl/map/update.hpp
index dc383b819e..74ab22dd8a 100644
--- a/src/mbgl/map/update.hpp
+++ b/src/mbgl/map/update.hpp
@@ -6,10 +6,9 @@ namespace mbgl {
enum class Update {
Nothing = 0,
+ Repaint = 1 << 0,
Classes = 1 << 2,
RecalculateStyle = 1 << 3,
- RenderStill = 1 << 4,
- Repaint = 1 << 5,
AnnotationStyle = 1 << 6,
AnnotationData = 1 << 7,
Layout = 1 << 8
diff --git a/src/mbgl/util/math.cpp b/src/mbgl/math/log2.cpp
index 7b1516c041..222e67dbd7 100644
--- a/src/mbgl/util/math.cpp
+++ b/src/mbgl/math/log2.cpp
@@ -1,4 +1,4 @@
-#include <mbgl/util/math.hpp>
+#include <mbgl/math/log2.hpp>
namespace mbgl {
namespace util {
@@ -21,15 +21,5 @@ uint32_t ceil_log2(uint64_t x) {
return y;
}
-double log2(double x) {
-// log2() is producing wrong results on ARMv5 binaries
-// running on ARMv7+ CPUs.
-#if defined(__ANDROID__)
- return std::log(x) / 0.6931471805599453; // log(x) / log(2)
-#else
- return ::log2(x);
-#endif
-}
-
} // namespace util
} // namespace mbgl
diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp
new file mode 100644
index 0000000000..38bbe89377
--- /dev/null
+++ b/src/mbgl/programs/attributes.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <mbgl/gl/attribute.hpp>
+
+#include <cstdint>
+
+namespace mbgl {
+namespace attributes {
+
+// Attributes common to several shaders.
+
+MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_pos);
+MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_offset);
+MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_extrude);
+MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, a_texture_pos);
+
+template <std::size_t N>
+struct a_data : gl::Attribute<a_data<N>, uint8_t, N> {
+ static constexpr auto name = "a_data";
+};
+
+} // namespace attributes
+} // namespace mbgl
diff --git a/src/mbgl/programs/circle_program.cpp b/src/mbgl/programs/circle_program.cpp
new file mode 100644
index 0000000000..d6bc439feb
--- /dev/null
+++ b/src/mbgl/programs/circle_program.cpp
@@ -0,0 +1,7 @@
+#include <mbgl/programs/circle_program.hpp>
+
+namespace mbgl {
+
+static_assert(sizeof(CircleProgram::Vertex) == 4, "expected CircleVertex size");
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/circle_program.hpp b/src/mbgl/programs/circle_program.hpp
new file mode 100644
index 0000000000..c9aea1d137
--- /dev/null
+++ b/src/mbgl/programs/circle_program.hpp
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/circle.hpp>
+#include <mbgl/util/geometry.hpp>
+
+namespace mbgl {
+
+namespace uniforms {
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_radius);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, u_stroke_color);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_stroke_width);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_stroke_opacity);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, u_scale_with_map);
+} // namespace uniforms
+
+using CircleAttributes = gl::Attributes<
+ attributes::a_pos>;
+
+class CircleProgram : public Program<
+ shaders::circle,
+ gl::Triangle,
+ CircleAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_color,
+ uniforms::u_radius,
+ uniforms::u_blur,
+ uniforms::u_stroke_color,
+ uniforms::u_stroke_width,
+ uniforms::u_stroke_opacity,
+ uniforms::u_scale_with_map,
+ uniforms::u_extrude_scale>>
+{
+public:
+ using Program::Program;
+
+ /*
+ * @param {number} x vertex position
+ * @param {number} y vertex position
+ * @param {number} ex extrude normal
+ * @param {number} ey extrude normal
+ */
+ static Vertex vertex(Point<int16_t> p, float ex, float ey) {
+ return Vertex {
+ {
+ static_cast<int16_t>((p.x * 2) + ((ex + 1) / 2)),
+ static_cast<int16_t>((p.y * 2) + ((ey + 1) / 2))
+ }
+ };
+ }
+};
+
+using CircleVertex = CircleProgram::Vertex;
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/collision_box_program.cpp b/src/mbgl/programs/collision_box_program.cpp
new file mode 100644
index 0000000000..d6a36e54a1
--- /dev/null
+++ b/src/mbgl/programs/collision_box_program.cpp
@@ -0,0 +1,7 @@
+#include <mbgl/programs/collision_box_program.hpp>
+
+namespace mbgl {
+
+static_assert(sizeof(CollisionBoxProgram::Vertex) == 10, "expected CollisionBoxVertex size");
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/collision_box_program.hpp b/src/mbgl/programs/collision_box_program.hpp
new file mode 100644
index 0000000000..26e38419a4
--- /dev/null
+++ b/src/mbgl/programs/collision_box_program.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/collision_box.hpp>
+#include <mbgl/util/geometry.hpp>
+
+#include <cmath>
+
+namespace mbgl {
+
+namespace uniforms {
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_maxzoom);
+} // namespace uniforms
+
+using CollisionBoxAttributes = gl::Attributes<
+ attributes::a_pos,
+ attributes::a_extrude,
+ attributes::a_data<2>>;
+
+class CollisionBoxProgram : public Program<
+ shaders::collision_box,
+ gl::Line,
+ CollisionBoxAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_scale,
+ uniforms::u_zoom,
+ uniforms::u_maxzoom>>
+{
+public:
+ using Program::Program;
+
+ static Vertex vertex(Point<float> a, Point<float> o, float maxzoom, float placementZoom) {
+ return Vertex {
+ {
+ static_cast<int16_t>(a.x),
+ static_cast<int16_t>(a.y)
+ },
+ {
+ static_cast<int16_t>(::round(o.x)),
+ static_cast<int16_t>(::round(o.y))
+ },
+ {
+ static_cast<uint8_t>(maxzoom * 10),
+ static_cast<uint8_t>(placementZoom * 10)
+ }
+ };
+ }
+};
+
+using CollisionBoxVertex = CollisionBoxProgram::Vertex;
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/debug_program.hpp b/src/mbgl/programs/debug_program.hpp
new file mode 100644
index 0000000000..cd4e08b1bc
--- /dev/null
+++ b/src/mbgl/programs/debug_program.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/debug.hpp>
+
+namespace mbgl {
+
+using DebugAttributes = gl::Attributes<
+ attributes::a_pos>;
+
+class DebugProgram : public Program<
+ shaders::debug,
+ gl::Line,
+ DebugAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_color>>
+{
+public:
+ using Program::Program;
+};
+
+using DebugVertex = DebugProgram::Vertex;
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/fill_program.cpp b/src/mbgl/programs/fill_program.cpp
new file mode 100644
index 0000000000..a8154d08f9
--- /dev/null
+++ b/src/mbgl/programs/fill_program.cpp
@@ -0,0 +1,47 @@
+#include <mbgl/programs/fill_program.hpp>
+#include <mbgl/sprite/sprite_atlas.hpp>
+#include <mbgl/style/cross_faded_property_evaluator.hpp>
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/map/transform_state.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+static_assert(sizeof(FillAttributes::Vertex) == 4, "expected FillVertex size");
+
+FillPatternUniforms::Values
+FillPatternUniforms::values(mat4 matrix,
+ float opacity,
+ Size framebufferSize,
+ const SpriteAtlasPosition& a,
+ const SpriteAtlasPosition& b,
+ const Faded<std::string>& fading,
+ const UnwrappedTileID& tileID,
+ const TransformState& state)
+{
+ int32_t tileSizeAtNearestZoom = util::tileSize * state.zoomScale(state.getIntegerZoom() - tileID.canonical.z);
+ int32_t pixelX = tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * state.zoomScale(tileID.canonical.z));
+ int32_t pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
+
+ return FillPatternUniforms::Values {
+ uniforms::u_matrix::Value{ matrix },
+ uniforms::u_opacity::Value{ opacity },
+ uniforms::u_world::Value{ framebufferSize },
+ uniforms::u_pattern_tl_a::Value{ a.tl },
+ uniforms::u_pattern_br_a::Value{ a.br },
+ uniforms::u_pattern_tl_b::Value{ b.tl },
+ uniforms::u_pattern_br_b::Value{ b.br },
+ uniforms::u_pattern_size_a::Value{ a.size },
+ uniforms::u_pattern_size_b::Value{ b.size },
+ uniforms::u_scale_a::Value{ fading.fromScale },
+ uniforms::u_scale_b::Value{ fading.toScale },
+ uniforms::u_mix::Value{ fading.t },
+ uniforms::u_image::Value{ 0 },
+ uniforms::u_pixel_coord_upper::Value{ std::array<float, 2> {{ float(pixelX >> 16), float(pixelY >> 16) }} },
+ uniforms::u_pixel_coord_lower::Value{ std::array<float, 2> {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }} },
+ uniforms::u_tile_units_to_pixels::Value{ 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom()) },
+ };
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/fill_program.hpp b/src/mbgl/programs/fill_program.hpp
new file mode 100644
index 0000000000..d885215c59
--- /dev/null
+++ b/src/mbgl/programs/fill_program.hpp
@@ -0,0 +1,123 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/fill.hpp>
+#include <mbgl/shader/fill_pattern.hpp>
+#include <mbgl/shader/fill_outline.hpp>
+#include <mbgl/shader/fill_outline_pattern.hpp>
+#include <mbgl/util/geometry.hpp>
+#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/size.hpp>
+
+#include <string>
+
+namespace mbgl {
+
+class SpriteAtlasPosition;
+class UnwrappedTileID;
+class TransformState;
+
+namespace style {
+template <class> class Faded;
+} // namespace style
+
+namespace uniforms {
+MBGL_DEFINE_UNIFORM_SCALAR(Size, u_world);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, u_outline_color);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale_a);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale_b);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_tile_units_to_pixels);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pixel_coord_upper);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pixel_coord_lower);
+} // namespace uniforms
+
+struct FillAttributes : gl::Attributes<
+ attributes::a_pos>
+{
+ static Vertex vertex(Point<int16_t> p) {
+ return Vertex {
+ {
+ p.x,
+ p.y
+ }
+ };
+ }
+};
+
+using FillVertex = FillAttributes::Vertex;
+
+struct FillUniforms : gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_color,
+ uniforms::u_outline_color,
+ uniforms::u_world>
+{};
+
+struct FillPatternUniforms : gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_world,
+ uniforms::u_pattern_tl_a,
+ uniforms::u_pattern_br_a,
+ uniforms::u_pattern_tl_b,
+ uniforms::u_pattern_br_b,
+ uniforms::u_pattern_size_a,
+ uniforms::u_pattern_size_b,
+ uniforms::u_scale_a,
+ uniforms::u_scale_b,
+ uniforms::u_mix,
+ uniforms::u_image,
+ uniforms::u_pixel_coord_upper,
+ uniforms::u_pixel_coord_lower,
+ uniforms::u_tile_units_to_pixels>
+{
+ static Values values(mat4 matrix,
+ float opacity,
+ Size framebufferSize,
+ const SpriteAtlasPosition&,
+ const SpriteAtlasPosition&,
+ const style::Faded<std::string>&,
+ const UnwrappedTileID&,
+ const TransformState&);
+};
+
+class FillProgram : public Program<
+ shaders::fill,
+ gl::Triangle,
+ FillAttributes,
+ FillUniforms>
+{
+ using Program::Program;
+};
+
+class FillPatternProgram : public Program<
+ shaders::fill_pattern,
+ gl::Triangle,
+ FillAttributes,
+ FillPatternUniforms>
+{
+ using Program::Program;
+};
+
+class FillOutlineProgram : public Program<
+ shaders::fill_outline,
+ gl::Line,
+ FillAttributes,
+ FillUniforms>
+{
+ using Program::Program;
+};
+
+class FillOutlinePatternProgram : public Program<
+ shaders::fill_outline_pattern,
+ gl::Line,
+ FillAttributes,
+ FillPatternUniforms>
+{
+ using Program::Program;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/line_program.cpp b/src/mbgl/programs/line_program.cpp
new file mode 100644
index 0000000000..f7054d3398
--- /dev/null
+++ b/src/mbgl/programs/line_program.cpp
@@ -0,0 +1,125 @@
+#include <mbgl/programs/line_program.hpp>
+#include <mbgl/style/layers/line_layer_properties.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/map/transform_state.hpp>
+#include <mbgl/util/mat2.hpp>
+#include <mbgl/sprite/sprite_atlas.hpp>
+#include <mbgl/geometry/line_atlas.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+static_assert(sizeof(LineAttributes::Vertex) == 8, "expected LineVertex size");
+
+template <class Values, class...Args>
+Values makeValues(const LinePaintProperties::Evaluated& properties,
+ const RenderTile& tile,
+ const TransformState& state,
+ const std::array<float, 2>& pixelsToGLUnits,
+ Args&&... args) {
+
+ return Values {
+ uniforms::u_matrix::Value{
+ tile.translatedMatrix(properties.get<LineTranslate>(),
+ properties.get<LineTranslateAnchor>(),
+ state)
+ },
+ uniforms::u_opacity::Value{ properties.get<LineOpacity>() },
+ uniforms::u_width::Value{ properties.get<LineWidth>() },
+ uniforms::u_gapwidth::Value{ properties.get<LineGapWidth>() },
+ uniforms::u_blur::Value{ properties.get<LineBlur>() },
+ uniforms::u_offset::Value{ properties.get<LineOffset>() },
+ uniforms::u_ratio::Value{ 1.0f / tile.id.pixelsToTileUnits(1.0, state.getZoom()) },
+ uniforms::u_gl_units_to_pixels::Value{{{ 1.0f / pixelsToGLUnits[0], 1.0f / pixelsToGLUnits[1] }}},
+ std::forward<Args>(args)...
+ };
+}
+
+LineProgram::UniformValues
+LineProgram::uniformValues(const LinePaintProperties::Evaluated& properties,
+ const RenderTile& tile,
+ const TransformState& state,
+ const std::array<float, 2>& pixelsToGLUnits) {
+ return makeValues<LineProgram::UniformValues>(
+ properties,
+ tile,
+ state,
+ pixelsToGLUnits,
+ uniforms::u_color::Value{ properties.get<LineColor>() }
+ );
+}
+
+LineSDFProgram::UniformValues
+LineSDFProgram::uniformValues(const LinePaintProperties::Evaluated& properties,
+ float pixelRatio,
+ const RenderTile& tile,
+ const TransformState& state,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const LinePatternPos& posA,
+ const LinePatternPos& posB,
+ float dashLineWidth,
+ float atlasWidth) {
+ const float widthA = posA.width * properties.get<LineDasharray>().fromScale * dashLineWidth;
+ const float widthB = posB.width * properties.get<LineDasharray>().toScale * dashLineWidth;
+
+ std::array<float, 2> scaleA {{
+ 1.0f / tile.id.pixelsToTileUnits(widthA, state.getIntegerZoom()),
+ -posA.height / 2.0f
+ }};
+
+ std::array<float, 2> scaleB {{
+ 1.0f / tile.id.pixelsToTileUnits(widthB, state.getIntegerZoom()),
+ -posB.height / 2.0f
+ }};
+
+ return makeValues<LineSDFProgram::UniformValues>(
+ properties,
+ tile,
+ state,
+ pixelsToGLUnits,
+ uniforms::u_color::Value{ properties.get<LineColor>() },
+ uniforms::u_patternscale_a::Value{ scaleA },
+ uniforms::u_patternscale_b::Value{ scaleB },
+ uniforms::u_tex_y_a::Value{ posA.y },
+ uniforms::u_tex_y_b::Value{ posB.y },
+ uniforms::u_mix::Value{ properties.get<LineDasharray>().t },
+ uniforms::u_sdfgamma::Value{ atlasWidth / (std::min(widthA, widthB) * 256.0f * pixelRatio) / 2.0f },
+ uniforms::u_image::Value{ 0 }
+ );
+}
+
+LinePatternProgram::UniformValues
+LinePatternProgram::uniformValues(const LinePaintProperties::Evaluated& properties,
+ const RenderTile& tile,
+ const TransformState& state,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const SpriteAtlasPosition& posA,
+ const SpriteAtlasPosition& posB) {
+ std::array<float, 2> sizeA {{
+ tile.id.pixelsToTileUnits(posA.size[0] * properties.get<LinePattern>().fromScale, state.getIntegerZoom()),
+ posA.size[1]
+ }};
+
+ std::array<float, 2> sizeB {{
+ tile.id.pixelsToTileUnits(posB.size[0] * properties.get<LinePattern>().toScale, state.getIntegerZoom()),
+ posB.size[1]
+ }};
+
+ return makeValues<LinePatternProgram::UniformValues>(
+ properties,
+ tile,
+ state,
+ pixelsToGLUnits,
+ uniforms::u_pattern_tl_a::Value{ posA.tl },
+ uniforms::u_pattern_br_a::Value{ posA.br },
+ uniforms::u_pattern_tl_b::Value{ posB.tl },
+ uniforms::u_pattern_br_b::Value{ posB.br },
+ uniforms::u_pattern_size_a::Value{ sizeA },
+ uniforms::u_pattern_size_b::Value{ sizeB },
+ uniforms::u_fade::Value{ properties.get<LinePattern>().t },
+ uniforms::u_image::Value{ 0 }
+ );
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/line_program.hpp b/src/mbgl/programs/line_program.hpp
new file mode 100644
index 0000000000..9b97cc47a9
--- /dev/null
+++ b/src/mbgl/programs/line_program.hpp
@@ -0,0 +1,177 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/line.hpp>
+#include <mbgl/shader/line_pattern.hpp>
+#include <mbgl/shader/line_sdf.hpp>
+#include <mbgl/style/layers/line_layer_properties.hpp>
+#include <mbgl/util/geometry.hpp>
+
+#include <cmath>
+
+namespace mbgl {
+
+class RenderTile;
+class TransformState;
+class LinePatternPos;
+class SpriteAtlasPosition;
+
+namespace uniforms {
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_ratio);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_width);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_gapwidth);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_offset);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_tex_y_a);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_tex_y_b);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_sdfgamma);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_fade);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_patternscale_a);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_patternscale_b);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_gl_units_to_pixels);
+} // namespace uniforms
+
+struct LineAttributes : gl::Attributes<
+ attributes::a_pos,
+ attributes::a_data<4>>
+{
+ /*
+ * @param p vertex position
+ * @param e extrude normal
+ * @param t texture normal
+ * @param dir direction of the line cap (-1/0/1)
+ */
+ static Vertex vertex(Point<int16_t> p, Point<double> e, Point<bool> t, int8_t dir, int32_t linesofar = 0) {
+ return Vertex {
+ {
+ static_cast<int16_t>((p.x * 2) | t.x),
+ static_cast<int16_t>((p.y * 2) | t.y)
+ },
+ {
+ // add 128 to store an byte in an unsigned byte
+ static_cast<uint8_t>(::round(extrudeScale * e.x) + 128),
+ static_cast<uint8_t>(::round(extrudeScale * e.y) + 128),
+
+ // Encode the -1/0/1 direction value into the first two bits of .z of a_data.
+ // Combine it with the lower 6 bits of `linesofar` (shifted by 2 bites to make
+ // room for the direction value). The upper 8 bits of `linesofar` are placed in
+ // the `w` component. `linesofar` is scaled down by `LINE_DISTANCE_SCALE` so that
+ // we can store longer distances while sacrificing precision.
+
+ // Encode the -1/0/1 direction value into .zw coordinates of a_data, which is normally covered
+ // by linesofar, so we need to merge them.
+ // The z component's first bit, as well as the sign bit is reserved for the direction,
+ // so we need to shift the linesofar.
+ static_cast<uint8_t>(((dir == 0 ? 0 : (dir < 0 ? -1 : 1 )) + 1) | ((linesofar & 0x3F) << 2)),
+ static_cast<uint8_t>(linesofar >> 6)
+ }
+ };
+ }
+
+ /*
+ * Scale the extrusion vector so that the normal length is this value.
+ * Contains the "texture" normals (-1..1). This is distinct from the extrude
+ * normals for line joins, because the x-value remains 0 for the texture
+ * normal array, while the extrude normal actually moves the vertex to create
+ * the acute/bevelled line join.
+ */
+ static const int8_t extrudeScale = 63;
+};
+
+using LineVertex = LineAttributes::Vertex;
+
+class LineProgram : public Program<
+ shaders::line,
+ gl::Triangle,
+ LineAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_width,
+ uniforms::u_gapwidth,
+ uniforms::u_blur,
+ uniforms::u_offset,
+ uniforms::u_ratio,
+ uniforms::u_gl_units_to_pixels,
+ uniforms::u_color>>
+{
+public:
+ using Program::Program;
+
+ static UniformValues uniformValues(const style::LinePaintProperties::Evaluated&,
+ const RenderTile&,
+ const TransformState&,
+ const std::array<float, 2>& pixelsToGLUnits);
+};
+
+class LinePatternProgram : public Program<
+ shaders::line_pattern,
+ gl::Triangle,
+ LineAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_width,
+ uniforms::u_gapwidth,
+ uniforms::u_blur,
+ uniforms::u_offset,
+ uniforms::u_ratio,
+ uniforms::u_gl_units_to_pixels,
+ uniforms::u_pattern_tl_a,
+ uniforms::u_pattern_br_a,
+ uniforms::u_pattern_tl_b,
+ uniforms::u_pattern_br_b,
+ uniforms::u_pattern_size_a,
+ uniforms::u_pattern_size_b,
+ uniforms::u_fade,
+ uniforms::u_image>>
+{
+public:
+ using Program::Program;
+
+ static UniformValues uniformValues(const style::LinePaintProperties::Evaluated&,
+ const RenderTile&,
+ const TransformState&,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const SpriteAtlasPosition& posA,
+ const SpriteAtlasPosition& posB);
+};
+
+class LineSDFProgram : public Program<
+ shaders::line_sdf,
+ gl::Triangle,
+ LineAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_width,
+ uniforms::u_gapwidth,
+ uniforms::u_blur,
+ uniforms::u_offset,
+ uniforms::u_ratio,
+ uniforms::u_gl_units_to_pixels,
+ uniforms::u_color,
+ uniforms::u_patternscale_a,
+ uniforms::u_patternscale_b,
+ uniforms::u_tex_y_a,
+ uniforms::u_tex_y_b,
+ uniforms::u_mix,
+ uniforms::u_sdfgamma,
+ uniforms::u_image>>
+{
+public:
+ using Program::Program;
+
+ static UniformValues uniformValues(const style::LinePaintProperties::Evaluated&,
+ float pixelRatio,
+ const RenderTile&,
+ const TransformState&,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const LinePatternPos& posA,
+ const LinePatternPos& posB,
+ float dashLineWidth,
+ float atlasWidth);
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/program.hpp b/src/mbgl/programs/program.hpp
new file mode 100644
index 0000000000..e5aae24997
--- /dev/null
+++ b/src/mbgl/programs/program.hpp
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <mbgl/gl/program.hpp>
+#include <mbgl/programs/program_parameters.hpp>
+
+#include <sstream>
+#include <cassert>
+
+namespace mbgl {
+
+template <class Shaders, class Primitive, class Attributes, class Uniforms>
+class Program : public gl::Program<Primitive, Attributes, Uniforms> {
+public:
+ using ParentType = gl::Program<Primitive, Attributes, Uniforms>;
+
+ Program(gl::Context& context, const ProgramParameters& programParameters)
+ : ParentType(context, vertexSource(programParameters), fragmentSource(programParameters))
+ {}
+
+ static std::string pixelRatioDefine(const ProgramParameters& parameters) {
+ std::ostringstream pixelRatioSS;
+ pixelRatioSS.imbue(std::locale("C"));
+ pixelRatioSS.setf(std::ios_base::showpoint);
+ pixelRatioSS << parameters.pixelRatio;
+ return std::string("#define DEVICE_PIXEL_RATIO ") + pixelRatioSS.str() + "\n";
+ }
+
+ static std::string fragmentSource(const ProgramParameters& parameters) {
+ std::string source = pixelRatioDefine(parameters) + Shaders::fragmentSource;
+ if (parameters.overdraw) {
+ assert(source.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos);
+ source.replace(source.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n");
+ }
+ return source;
+ }
+
+ static std::string vertexSource(const ProgramParameters& parameters) {
+ return pixelRatioDefine(parameters) + Shaders::vertexSource;
+ }
+
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/program_parameters.hpp b/src/mbgl/programs/program_parameters.hpp
new file mode 100644
index 0000000000..ad8cbf1bf8
--- /dev/null
+++ b/src/mbgl/programs/program_parameters.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+namespace mbgl {
+
+class ProgramParameters {
+public:
+ ProgramParameters(float pixelRatio_ = 1.0, bool overdraw_ = false)
+ : pixelRatio(pixelRatio_),
+ overdraw(overdraw_) {}
+
+ float pixelRatio;
+ bool overdraw;
+};
+
+} // namespace mbgl
+
diff --git a/src/mbgl/programs/programs.hpp b/src/mbgl/programs/programs.hpp
new file mode 100644
index 0000000000..dd71c2ce97
--- /dev/null
+++ b/src/mbgl/programs/programs.hpp
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <mbgl/programs/circle_program.hpp>
+#include <mbgl/programs/fill_program.hpp>
+#include <mbgl/programs/line_program.hpp>
+#include <mbgl/programs/raster_program.hpp>
+#include <mbgl/programs/symbol_program.hpp>
+#include <mbgl/programs/debug_program.hpp>
+#include <mbgl/programs/collision_box_program.hpp>
+#include <mbgl/programs/program_parameters.hpp>
+
+namespace mbgl {
+
+class Programs {
+public:
+ Programs(gl::Context& context, const ProgramParameters& programParameters)
+ : circle(context, programParameters),
+ fill(context, programParameters),
+ fillPattern(context, programParameters),
+ fillOutline(context, programParameters),
+ fillOutlinePattern(context, programParameters),
+ line(context, programParameters),
+ lineSDF(context, programParameters),
+ linePattern(context, programParameters),
+ raster(context, programParameters),
+ symbolIcon(context, programParameters),
+ symbolIconSDF(context, programParameters),
+ symbolGlyph(context, programParameters),
+ debug(context, ProgramParameters(programParameters.pixelRatio, false)),
+ collisionBox(context, ProgramParameters(programParameters.pixelRatio, false)) {
+ }
+
+ CircleProgram circle;
+ FillProgram fill;
+ FillPatternProgram fillPattern;
+ FillOutlineProgram fillOutline;
+ FillOutlinePatternProgram fillOutlinePattern;
+ LineProgram line;
+ LineSDFProgram lineSDF;
+ LinePatternProgram linePattern;
+ RasterProgram raster;
+ SymbolIconProgram symbolIcon;
+ SymbolSDFProgram symbolIconSDF;
+ SymbolSDFProgram symbolGlyph;
+
+ DebugProgram debug;
+ CollisionBoxProgram collisionBox;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/raster_program.cpp b/src/mbgl/programs/raster_program.cpp
new file mode 100644
index 0000000000..ebec4c68cc
--- /dev/null
+++ b/src/mbgl/programs/raster_program.cpp
@@ -0,0 +1,7 @@
+#include <mbgl/programs/raster_program.hpp>
+
+namespace mbgl {
+
+static_assert(sizeof(RasterProgram::Vertex) == 8, "expected RasterVertex size");
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/raster_program.hpp b/src/mbgl/programs/raster_program.hpp
new file mode 100644
index 0000000000..9aa25cf90c
--- /dev/null
+++ b/src/mbgl/programs/raster_program.hpp
@@ -0,0 +1,67 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/raster.hpp>
+#include <mbgl/util/geometry.hpp>
+
+namespace mbgl {
+
+namespace uniforms {
+MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_image0);
+MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_image1);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_fade_t);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_buffer_scale);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_brightness_low);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_brightness_high);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_saturation_factor);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_contrast_factor);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale_parent);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 3, u_spin_weights);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_tl_parent);
+} // namespace uniforms
+
+using RasterAttributes = gl::Attributes<
+ attributes::a_pos,
+ attributes::a_texture_pos>;
+
+class RasterProgram : public Program<
+ shaders::raster,
+ gl::Triangle,
+ RasterAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_image0,
+ uniforms::u_image1,
+ uniforms::u_opacity,
+ uniforms::u_fade_t,
+ uniforms::u_brightness_low,
+ uniforms::u_brightness_high,
+ uniforms::u_saturation_factor,
+ uniforms::u_contrast_factor,
+ uniforms::u_spin_weights,
+ uniforms::u_buffer_scale,
+ uniforms::u_scale_parent,
+ uniforms::u_tl_parent>>
+{
+public:
+ using Program::Program;
+
+ static Vertex vertex(Point<int16_t> p, Point<uint16_t> t) {
+ return Vertex {
+ {
+ p.x,
+ p.y
+ },
+ {
+ t.x,
+ t.y
+ }
+ };
+ }
+};
+
+using RasterVertex = RasterProgram::Vertex;
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/symbol_program.cpp b/src/mbgl/programs/symbol_program.cpp
new file mode 100644
index 0000000000..d609dada8d
--- /dev/null
+++ b/src/mbgl/programs/symbol_program.cpp
@@ -0,0 +1,145 @@
+#include <mbgl/programs/symbol_program.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/map/transform_state.hpp>
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+static_assert(sizeof(SymbolAttributes::Vertex) == 16, "expected SymbolVertex size");
+
+template <class Values, class...Args>
+Values makeValues(const style::SymbolPropertyValues& values,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile& tile,
+ const TransformState& state,
+ Args&&... args) {
+ std::array<float, 2> extrudeScale;
+
+ const float scale = values.paintSize / values.sdfScale;
+ if (values.pitchAlignment == AlignmentType::Map) {
+ extrudeScale.fill(tile.id.pixelsToTileUnits(1, state.getZoom()) * scale);
+ } else {
+ extrudeScale = {{
+ pixelsToGLUnits[0] * scale * state.getCameraToCenterDistance(),
+ pixelsToGLUnits[1] * scale * state.getCameraToCenterDistance()
+ }};
+ }
+
+ // adjust min/max zooms for variable font sies
+ float zoomAdjust = std::log(values.paintSize / values.layoutSize) / std::log(2);
+
+ return Values {
+ uniforms::u_matrix::Value{ tile.translatedMatrix(values.translate,
+ values.translateAnchor,
+ state) },
+ uniforms::u_opacity::Value{ values.opacity },
+ uniforms::u_extrude_scale::Value{ extrudeScale },
+ uniforms::u_texsize::Value{ std::array<float, 2> {{ float(texsize.width) / 4, float(texsize.height) / 4 }} },
+ uniforms::u_zoom::Value{ float((state.getZoom() - zoomAdjust) * 10) },
+ uniforms::u_rotate_with_map::Value{ values.rotationAlignment == AlignmentType::Map },
+ uniforms::u_texture::Value{ 0 },
+ uniforms::u_fadetexture::Value{ 1 },
+ std::forward<Args>(args)...
+ };
+}
+
+SymbolIconProgram::UniformValues
+SymbolIconProgram::uniformValues(const style::SymbolPropertyValues& values,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile& tile,
+ const TransformState& state)
+{
+ return makeValues<SymbolIconProgram::UniformValues>(
+ values,
+ texsize,
+ pixelsToGLUnits,
+ tile,
+ state
+ );
+}
+
+static SymbolSDFProgram::UniformValues makeSDFValues(const style::SymbolPropertyValues& values,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile& tile,
+ const TransformState& state,
+ float pixelRatio,
+ Color color,
+ float buffer,
+ float gammaAdjust)
+{
+ // The default gamma value has to be adjust for the current pixelratio so that we're not
+ // drawing blurry font on retina screens.
+ const float gammaBase = 0.105 * values.sdfScale / values.paintSize / pixelRatio;
+ const float gammaScale = (values.pitchAlignment == AlignmentType::Map
+ ? 1.0 / std::cos(state.getPitch())
+ : 1.0) / state.getCameraToCenterDistance();
+
+ return makeValues<SymbolSDFProgram::UniformValues>(
+ values,
+ texsize,
+ pixelsToGLUnits,
+ tile,
+ state,
+ uniforms::u_color::Value{ color },
+ uniforms::u_buffer::Value{ buffer },
+ uniforms::u_gamma::Value{ (gammaBase + gammaAdjust) * gammaScale },
+ uniforms::u_pitch::Value{ state.getPitch() },
+ uniforms::u_bearing::Value{ -1.0f * state.getAngle() },
+ uniforms::u_aspect_ratio::Value{ (state.getSize().width * 1.0f) / (state.getSize().height * 1.0f) },
+ uniforms::u_pitch_with_map::Value{ values.pitchAlignment == AlignmentType::Map }
+ );
+}
+
+SymbolSDFProgram::UniformValues
+SymbolSDFProgram::haloUniformValues(const style::SymbolPropertyValues& values,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile& tile,
+ const TransformState& state,
+ float pixelRatio)
+{
+ const float scale = values.paintSize / values.sdfScale;
+ const float sdfPx = 8.0f;
+ const float blurOffset = 1.19f;
+ const float haloOffset = 6.0f;
+
+ return makeSDFValues(
+ values,
+ texsize,
+ pixelsToGLUnits,
+ tile,
+ state,
+ pixelRatio,
+ values.haloColor,
+ (haloOffset - values.haloWidth / scale) / sdfPx,
+ values.haloBlur * blurOffset / scale / sdfPx
+ );
+}
+
+SymbolSDFProgram::UniformValues
+SymbolSDFProgram::foregroundUniformValues(const style::SymbolPropertyValues& values,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile& tile,
+ const TransformState& state,
+ float pixelRatio)
+{
+ return makeSDFValues(
+ values,
+ texsize,
+ pixelsToGLUnits,
+ tile,
+ state,
+ pixelRatio,
+ values.color,
+ (256.0f - 64.0f) / 256.0f,
+ 0
+ );
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
new file mode 100644
index 0000000000..be987551c0
--- /dev/null
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -0,0 +1,136 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/symbol_icon.hpp>
+#include <mbgl/shader/symbol_sdf.hpp>
+#include <mbgl/util/geometry.hpp>
+#include <mbgl/util/size.hpp>
+
+#include <cmath>
+#include <array>
+
+namespace mbgl {
+
+namespace style {
+class SymbolPropertyValues;
+} // namespace style
+
+class RenderTile;
+class TransformState;
+
+namespace uniforms {
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_texsize);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, u_rotate_with_map);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, u_pitch_with_map);
+MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_texture);
+MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_fadetexture);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_buffer);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_gamma);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_aspect_ratio);
+} // namespace uniforms
+
+struct SymbolAttributes : gl::Attributes<
+ attributes::a_pos,
+ attributes::a_offset,
+ attributes::a_texture_pos,
+ attributes::a_data<4>>
+{
+ static Vertex vertex(Point<float> a,
+ Point<float> o,
+ uint16_t tx,
+ uint16_t ty,
+ float minzoom,
+ float maxzoom,
+ float labelminzoom,
+ uint8_t labelangle) {
+ return Vertex {
+ {
+ static_cast<int16_t>(a.x),
+ static_cast<int16_t>(a.y)
+ },
+ {
+ static_cast<int16_t>(::round(o.x * 64)), // use 1/64 pixels for placement
+ static_cast<int16_t>(::round(o.y * 64))
+ },
+ {
+ static_cast<uint16_t>(tx / 4),
+ static_cast<uint16_t>(ty / 4)
+ },
+ {
+ static_cast<uint8_t>(labelminzoom * 10), // 1/10 zoom levels: z16 == 160
+ static_cast<uint8_t>(labelangle),
+ static_cast<uint8_t>(minzoom * 10),
+ static_cast<uint8_t>(::fmin(maxzoom, 25) * 10)
+ }
+ };
+ }
+};
+
+using SymbolVertex = SymbolAttributes::Vertex;
+
+class SymbolIconProgram : public Program<
+ shaders::symbol_icon,
+ gl::Triangle,
+ SymbolAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_extrude_scale,
+ uniforms::u_texsize,
+ uniforms::u_zoom,
+ uniforms::u_rotate_with_map,
+ uniforms::u_texture,
+ uniforms::u_fadetexture>>
+{
+public:
+ using Program::Program;
+
+ static UniformValues uniformValues(const style::SymbolPropertyValues&,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile&,
+ const TransformState&);
+};
+
+class SymbolSDFProgram : public Program<
+ shaders::symbol_sdf,
+ gl::Triangle,
+ SymbolAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_extrude_scale,
+ uniforms::u_texsize,
+ uniforms::u_zoom,
+ uniforms::u_rotate_with_map,
+ uniforms::u_texture,
+ uniforms::u_fadetexture,
+ uniforms::u_color,
+ uniforms::u_buffer,
+ uniforms::u_gamma,
+ uniforms::u_pitch,
+ uniforms::u_bearing,
+ uniforms::u_aspect_ratio,
+ uniforms::u_pitch_with_map>>
+{
+public:
+ using Program::Program;
+
+ static UniformValues haloUniformValues(const style::SymbolPropertyValues&,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile&,
+ const TransformState&,
+ float pixelRatio);
+
+ static UniformValues foregroundUniformValues(const style::SymbolPropertyValues&,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile&,
+ const TransformState&,
+ float pixelRatio);
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/uniforms.hpp b/src/mbgl/programs/uniforms.hpp
new file mode 100644
index 0000000000..e0c5a0d361
--- /dev/null
+++ b/src/mbgl/programs/uniforms.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <mbgl/gl/uniform.hpp>
+#include <mbgl/util/color.hpp>
+
+namespace mbgl {
+namespace uniforms {
+
+// Uniforms common to several shaders.
+
+MBGL_DEFINE_UNIFORM_MATRIX(double, 4, u_matrix);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_opacity);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, u_color);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_blur);
+
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_zoom);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_pitch);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_bearing);
+
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_extrude_scale);
+
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_tl_a);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_br_a);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_tl_b);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_br_b);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_size_a);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_size_b);
+
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_mix);
+MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_image);
+
+} // namespace uniforms
+} // namespace mbgl
diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp
index 2c3c7a6e47..49619c14f7 100644
--- a/src/mbgl/renderer/bucket.hpp
+++ b/src/mbgl/renderer/bucket.hpp
@@ -5,9 +5,6 @@
#include <atomic>
-#define BUFFER_OFFSET_0 ((int8_t*)nullptr)
-#define BUFFER_OFFSET(i) ((BUFFER_OFFSET_0) + (i))
-
namespace mbgl {
class Painter;
@@ -38,8 +35,6 @@ public:
virtual bool hasData() const = 0;
- virtual bool needsClipping() const = 0;
-
bool needsUpload() const {
return !uploaded;
}
diff --git a/src/mbgl/renderer/circle_bucket.cpp b/src/mbgl/renderer/circle_bucket.cpp
index f12139d004..ba2285c4eb 100644
--- a/src/mbgl/renderer/circle_bucket.cpp
+++ b/src/mbgl/renderer/circle_bucket.cpp
@@ -1,8 +1,8 @@
#include <mbgl/renderer/circle_bucket.hpp>
#include <mbgl/renderer/painter.hpp>
-#include <mbgl/gl/gl.hpp>
+#include <mbgl/gl/context.hpp>
-#include <mbgl/shader/circle_shader.hpp>
+#include <mbgl/programs/circle_program.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/util/constants.hpp>
@@ -13,10 +13,6 @@ using namespace style;
CircleBucket::CircleBucket(MapMode mode_) : mode(mode_) {
}
-CircleBucket::~CircleBucket() {
- // Do not remove. header file only contains forward definitions to unique pointers.
-}
-
void CircleBucket::upload(gl::Context& context) {
vertexBuffer = context.createVertexBuffer(std::move(vertices));
indexBuffer = context.createIndexBuffer(std::move(triangles));
@@ -31,18 +27,16 @@ void CircleBucket::render(Painter& painter,
}
bool CircleBucket::hasData() const {
- return !groups.empty();
-}
-
-bool CircleBucket::needsClipping() const {
- return true;
+ return !segments.empty();
}
void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) {
+ constexpr const uint16_t vertexLength = 4;
+
for (auto& circle : geometryCollection) {
- for(auto & geometry : circle) {
- auto x = geometry.x;
- auto y = geometry.y;
+ for(auto& point : circle) {
+ auto x = point.x;
+ auto y = point.y;
// Do not include points that are outside the tile boundaries.
// Include all points in Still mode. You need to include points from
@@ -50,6 +44,11 @@ void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) {
if ((mode != MapMode::Still) &&
(x < 0 || x >= util::EXTENT || y < 0 || y >= util::EXTENT)) continue;
+ if (segments.empty() || segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
+ // Move to a new segments because the old one can't hold the geometry.
+ segments.emplace_back(vertices.vertexSize(), triangles.indexSize());
+ }
+
// this geometry will be of the Point type, and we'll derive
// two triangles from it.
//
@@ -59,47 +58,23 @@ void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) {
// │ 1 2 │
// └─────────┘
//
- vertices.emplace_back(x, y, -1, -1); // 1
- vertices.emplace_back(x, y, 1, -1); // 2
- vertices.emplace_back(x, y, 1, 1); // 3
- vertices.emplace_back(x, y, -1, 1); // 4
-
- if (!groups.size() || groups.back().vertexLength + 4 > 65535) {
- // Move to a new group because the old one can't hold the geometry.
- groups.emplace_back();
- }
+ vertices.emplace_back(CircleProgram::vertex(point, -1, -1)); // 1
+ vertices.emplace_back(CircleProgram::vertex(point, 1, -1)); // 2
+ vertices.emplace_back(CircleProgram::vertex(point, 1, 1)); // 3
+ vertices.emplace_back(CircleProgram::vertex(point, -1, 1)); // 4
- auto& group = groups.back();
- uint16_t index = group.vertexLength;
+ auto& segment = segments.back();
+ assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
+ uint16_t index = segment.vertexLength;
// 1, 2, 3
// 1, 4, 3
- triangles.emplace_back(index,
- static_cast<uint16_t>(index + 1),
- static_cast<uint16_t>(index + 2));
- triangles.emplace_back(index,
- static_cast<uint16_t>(index + 3),
- static_cast<uint16_t>(index + 2));
-
- group.vertexLength += 4;
- group.indexLength += 2;
- }
- }
-}
-
-void CircleBucket::drawCircles(CircleShader& shader, gl::Context& context, PaintMode paintMode) {
- GLbyte* vertexIndex = BUFFER_OFFSET(0);
- GLbyte* elementsIndex = BUFFER_OFFSET(0);
+ triangles.emplace_back(index, index + 1, index + 2);
+ triangles.emplace_back(index, index + 3, index + 2);
- for (auto& group : groups) {
- if (!group.indexLength) continue;
-
- group.getVAO(shader, paintMode).bind(shader, *vertexBuffer, *indexBuffer, vertexIndex, context);
-
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT, elementsIndex));
-
- vertexIndex += group.vertexLength * vertexBuffer->vertexSize;
- elementsIndex += group.indexLength * indexBuffer->primitiveSize;
+ segment.vertexLength += vertexLength;
+ segment.indexLength += 6;
+ }
}
}
diff --git a/src/mbgl/renderer/circle_bucket.hpp b/src/mbgl/renderer/circle_bucket.hpp
index 2f3faccdec..af7041a238 100644
--- a/src/mbgl/renderer/circle_bucket.hpp
+++ b/src/mbgl/renderer/circle_bucket.hpp
@@ -1,39 +1,31 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/renderer/element_group.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/gl/index_buffer.hpp>
-#include <mbgl/shader/circle_vertex.hpp>
+#include <mbgl/gl/segment.hpp>
+#include <mbgl/programs/circle_program.hpp>
namespace mbgl {
-class CircleShader;
-
class CircleBucket : public Bucket {
public:
CircleBucket(const MapMode);
- ~CircleBucket() override;
void upload(gl::Context&) override;
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;
bool hasData() const override;
- bool needsClipping() const override;
void addGeometry(const GeometryCollection&);
- void drawCircles(CircleShader&, gl::Context&, PaintMode);
-
-private:
- std::vector<CircleVertex> vertices;
- std::vector<gl::Triangle> triangles;
-
- std::vector<ElementGroup<CircleShader>> groups;
+ gl::VertexVector<CircleVertex> vertices;
+ gl::IndexVector<gl::Triangles> triangles;
+ gl::SegmentVector<CircleAttributes> segments;
optional<gl::VertexBuffer<CircleVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
+ optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
const MapMode mode;
};
diff --git a/src/mbgl/renderer/debug_bucket.cpp b/src/mbgl/renderer/debug_bucket.cpp
index c47ae434be..167df4376f 100644
--- a/src/mbgl/renderer/debug_bucket.cpp
+++ b/src/mbgl/renderer/debug_bucket.cpp
@@ -1,25 +1,30 @@
#include <mbgl/renderer/debug_bucket.hpp>
#include <mbgl/renderer/painter.hpp>
-#include <mbgl/shader/fill_shader.hpp>
-#include <mbgl/shader/fill_vertex.hpp>
+#include <mbgl/programs/fill_program.hpp>
#include <mbgl/geometry/debug_font_data.hpp>
#include <mbgl/util/string.hpp>
-#include <mbgl/gl/gl.hpp>
-
#include <cmath>
#include <string>
#include <vector>
namespace mbgl {
-std::vector<FillVertex> buildTextVertices(const OverscaledTileID& id,
- const bool renderable,
- const bool complete,
- optional<Timestamp> modified,
- optional<Timestamp> expires,
- MapDebugOptions debugMode) {
- std::vector<FillVertex> textPoints;
+DebugBucket::DebugBucket(const OverscaledTileID& id,
+ const bool renderable_,
+ const bool complete_,
+ optional<Timestamp> modified_,
+ optional<Timestamp> expires_,
+ MapDebugOptions debugMode_,
+ gl::Context& context)
+ : renderable(renderable_),
+ complete(complete_),
+ modified(std::move(modified_)),
+ expires(std::move(expires_)),
+ debugMode(debugMode_) {
+
+ gl::VertexVector<FillVertex> vertices;
+ gl::IndexVector<gl::Lines> indices;
auto addText = [&] (const std::string& text, double left, double baseline, double scale) {
for (uint8_t c : text) {
@@ -38,9 +43,11 @@ std::vector<FillVertex> buildTextVertices(const OverscaledTileID& id,
int16_t(::round(baseline - glyph.data[j + 1] * scale))
};
+ vertices.emplace_back(FillAttributes::vertex(p));
+
if (prev) {
- textPoints.emplace_back(prev->x, prev->y);
- textPoints.emplace_back(p.x, p.y);
+ indices.emplace_back(vertices.vertexSize() - 2,
+ vertices.vertexSize() - 1);
}
prev = p;
@@ -67,36 +74,10 @@ std::vector<FillVertex> buildTextVertices(const OverscaledTileID& id,
addText(expiresText, 50, baseline + 200, 5);
}
- return textPoints;
-}
-
-DebugBucket::DebugBucket(const OverscaledTileID& id,
- const bool renderable_,
- const bool complete_,
- optional<Timestamp> modified_,
- optional<Timestamp> expires_,
- MapDebugOptions debugMode_,
- gl::Context& context)
- : renderable(renderable_),
- complete(complete_),
- modified(std::move(modified_)),
- expires(std::move(expires_)),
- debugMode(debugMode_),
- vertexBuffer(context.createVertexBuffer(buildTextVertices(id, renderable_, complete_, modified_, expires_, debugMode_))) {
-}
+ segments.emplace_back(0, 0, vertices.vertexSize(), indices.indexSize());
-void DebugBucket::drawLines(FillShader& shader, gl::Context& context) {
- if (vertexBuffer.vertexCount != 0) {
- array.bind(shader, vertexBuffer, BUFFER_OFFSET_0, context);
- MBGL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(vertexBuffer.vertexCount)));
- }
-}
-
-void DebugBucket::drawPoints(FillShader& shader, gl::Context& context) {
- if (vertexBuffer.vertexCount != 0) {
- array.bind(shader, vertexBuffer, BUFFER_OFFSET_0, context);
- MBGL_CHECK_ERROR(glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(vertexBuffer.vertexCount)));
- }
+ vertexBuffer = context.createVertexBuffer(std::move(vertices));
+ indexBuffer = context.createIndexBuffer(std::move(indices));
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/debug_bucket.hpp b/src/mbgl/renderer/debug_bucket.hpp
index 89087f0010..4676381789 100644
--- a/src/mbgl/renderer/debug_bucket.hpp
+++ b/src/mbgl/renderer/debug_bucket.hpp
@@ -6,13 +6,12 @@
#include <mbgl/util/optional.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
-#include <mbgl/gl/vao.hpp>
-#include <mbgl/shader/fill_vertex.hpp>
+#include <mbgl/gl/index_buffer.hpp>
+#include <mbgl/programs/debug_program.hpp>
namespace mbgl {
class OverscaledTileID;
-class FillShader;
namespace gl {
class Context;
@@ -28,18 +27,15 @@ public:
MapDebugOptions,
gl::Context&);
- void drawLines(FillShader&, gl::Context&);
- void drawPoints(FillShader&, gl::Context&);
-
const bool renderable;
const bool complete;
const optional<Timestamp> modified;
const optional<Timestamp> expires;
const MapDebugOptions debugMode;
-private:
- gl::VertexBuffer<FillVertex> vertexBuffer;
- gl::VertexArrayObject array;
+ gl::SegmentVector<DebugAttributes> segments;
+ optional<gl::VertexBuffer<DebugVertex>> vertexBuffer;
+ optional<gl::IndexBuffer<gl::Lines>> indexBuffer;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/element_group.hpp b/src/mbgl/renderer/element_group.hpp
deleted file mode 100644
index 59b5c3068d..0000000000
--- a/src/mbgl/renderer/element_group.hpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/vao.hpp>
-#include <mbgl/renderer/render_pass.hpp>
-
-namespace mbgl {
-
-template <class... Shaders>
-struct ElementGroup {
- template <class Shader>
- struct VAOs {
- gl::VertexArrayObject normalVAO;
- gl::VertexArrayObject overdrawVAO;
- };
-
- std::tuple<VAOs<Shaders>...> vaos;
-
- template <class Shader>
- gl::VertexArrayObject& getVAO(const Shader&, PaintMode paintMode) {
- auto& vao = std::get<VAOs<Shader>>(vaos);
- return paintMode == PaintMode::Overdraw ? vao.overdrawVAO : vao.normalVAO;
- }
-
- std::size_t vertexLength = 0;
- std::size_t indexLength = 0;
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp
index cd4277cabc..b89e982057 100644
--- a/src/mbgl/renderer/fill_bucket.cpp
+++ b/src/mbgl/renderer/fill_bucket.cpp
@@ -1,12 +1,8 @@
#include <mbgl/renderer/fill_bucket.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/renderer/painter.hpp>
-#include <mbgl/shader/fill_shader.hpp>
-#include <mbgl/shader/fill_pattern_shader.hpp>
-#include <mbgl/shader/fill_outline_shader.hpp>
-#include <mbgl/shader/fill_outline_pattern_shader.hpp>
-#include <mbgl/gl/gl.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/programs/fill_program.hpp>
+#include <mbgl/util/logging.hpp>
#include <mapbox/earcut.hpp>
@@ -30,11 +26,6 @@ using namespace style;
struct GeometryTooLongException : std::exception {};
-FillBucket::FillBucket() {
-}
-
-FillBucket::~FillBucket() = default;
-
void FillBucket::addGeometry(const GeometryCollection& geometry) {
for (auto& polygon : classifyRings(geometry)) {
// Optimize polygons with many interior rings for earcut tesselation.
@@ -44,34 +35,36 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) {
for (const auto& ring : polygon) {
totalVertices += ring.size();
- if (totalVertices > 65535)
+ if (totalVertices > std::numeric_limits<uint16_t>::max())
throw GeometryTooLongException();
}
+ std::size_t startVertices = vertices.vertexSize();
+
for (const auto& ring : polygon) {
std::size_t nVertices = ring.size();
if (nVertices == 0)
continue;
- if (lineGroups.empty() || lineGroups.back().vertexLength + nVertices > 65535)
- lineGroups.emplace_back();
+ if (lineSegments.empty() || lineSegments.back().vertexLength + nVertices > std::numeric_limits<uint16_t>::max()) {
+ lineSegments.emplace_back(vertices.vertexSize(), lines.indexSize());
+ }
- auto& lineGroup = lineGroups.back();
- uint16_t lineIndex = lineGroup.vertexLength;
+ auto& lineSegment = lineSegments.back();
+ assert(lineSegment.vertexLength <= std::numeric_limits<uint16_t>::max());
+ uint16_t lineIndex = lineSegment.vertexLength;
- vertices.emplace_back(ring[0].x, ring[0].y);
- lines.emplace_back(static_cast<uint16_t>(lineIndex + nVertices - 1),
- static_cast<uint16_t>(lineIndex));
+ vertices.emplace_back(FillAttributes::vertex(ring[0]));
+ lines.emplace_back(lineIndex + nVertices - 1, lineIndex);
for (uint32_t i = 1; i < nVertices; i++) {
- vertices.emplace_back(ring[i].x, ring[i].y);
- lines.emplace_back(static_cast<uint16_t>(lineIndex + i - 1),
- static_cast<uint16_t>(lineIndex + i));
+ vertices.emplace_back(FillAttributes::vertex(ring[i]));
+ lines.emplace_back(lineIndex + i - 1, lineIndex + i);
}
- lineGroup.vertexLength += nVertices;
- lineGroup.indexLength += nVertices;
+ lineSegment.vertexLength += nVertices;
+ lineSegment.indexLength += nVertices * 2;
}
std::vector<uint32_t> indices = mapbox::earcut(polygon);
@@ -79,21 +72,22 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) {
std::size_t nIndicies = indices.size();
assert(nIndicies % 3 == 0);
- if (triangleGroups.empty() || triangleGroups.back().vertexLength + totalVertices > 65535) {
- triangleGroups.emplace_back();
+ if (triangleSegments.empty() || triangleSegments.back().vertexLength + totalVertices > std::numeric_limits<uint16_t>::max()) {
+ triangleSegments.emplace_back(startVertices, triangles.indexSize());
}
- auto& triangleGroup = triangleGroups.back();
- uint16_t triangleIndex = triangleGroup.vertexLength;
+ auto& triangleSegment = triangleSegments.back();
+ assert(triangleSegment.vertexLength <= std::numeric_limits<uint16_t>::max());
+ uint16_t triangleIndex = triangleSegment.vertexLength;
for (uint32_t i = 0; i < nIndicies; i += 3) {
- triangles.emplace_back(static_cast<uint16_t>(triangleIndex + indices[i]),
- static_cast<uint16_t>(triangleIndex + indices[i + 1]),
- static_cast<uint16_t>(triangleIndex + indices[i + 2]));
+ triangles.emplace_back(triangleIndex + indices[i],
+ triangleIndex + indices[i + 1],
+ triangleIndex + indices[i + 2]);
}
- triangleGroup.vertexLength += totalVertices;
- triangleGroup.indexLength += nIndicies / 3;
+ triangleSegment.vertexLength += totalVertices;
+ triangleSegment.indexLength += nIndicies;
}
}
@@ -114,71 +108,7 @@ void FillBucket::render(Painter& painter,
}
bool FillBucket::hasData() const {
- return !triangleGroups.empty() || !lineGroups.empty();
-}
-
-bool FillBucket::needsClipping() const {
- return true;
-}
-
-void FillBucket::drawElements(FillShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : triangleGroups) {
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *triangleIndexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * triangleIndexBuffer->primitiveSize;
- }
-}
-
-void FillBucket::drawElements(FillPatternShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : triangleGroups) {
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *triangleIndexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * triangleIndexBuffer->primitiveSize;
- }
-}
-
-void FillBucket::drawVertices(FillOutlineShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : lineGroups) {
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *lineIndexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_LINES, static_cast<GLsizei>(group.indexLength * 2), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * lineIndexBuffer->primitiveSize;
- }
-}
-
-void FillBucket::drawVertices(FillOutlinePatternShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : lineGroups) {
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *lineIndexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_LINES, static_cast<GLsizei>(group.indexLength * 2), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * lineIndexBuffer->primitiveSize;
- }
+ return !triangleSegments.empty() || !lineSegments.empty();
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/fill_bucket.hpp b/src/mbgl/renderer/fill_bucket.hpp
index 34cd886687..edb1521c1d 100644
--- a/src/mbgl/renderer/fill_bucket.hpp
+++ b/src/mbgl/renderer/fill_bucket.hpp
@@ -1,50 +1,33 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/renderer/element_group.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/gl/index_buffer.hpp>
-#include <mbgl/shader/fill_vertex.hpp>
+#include <mbgl/gl/segment.hpp>
+#include <mbgl/programs/fill_program.hpp>
#include <vector>
-#include <memory>
namespace mbgl {
-class FillShader;
-class FillPatternShader;
-class FillOutlineShader;
-class FillOutlinePatternShader;
-
class FillBucket : public Bucket {
public:
- FillBucket();
- ~FillBucket() override;
-
void upload(gl::Context&) override;
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;
bool hasData() const override;
- bool needsClipping() const override;
void addGeometry(const GeometryCollection&);
- void drawElements(FillShader&, gl::Context&, PaintMode);
- void drawElements(FillPatternShader&, gl::Context&, PaintMode);
- void drawVertices(FillOutlineShader&, gl::Context&, PaintMode);
- void drawVertices(FillOutlinePatternShader&, gl::Context&, PaintMode);
-
-private:
- std::vector<FillVertex> vertices;
- std::vector<gl::Line> lines;
- std::vector<gl::Triangle> triangles;
-
- std::vector<ElementGroup<FillOutlineShader, FillOutlinePatternShader>> lineGroups;
- std::vector<ElementGroup<FillShader, FillPatternShader>> triangleGroups;
+ gl::VertexVector<FillVertex> vertices;
+ gl::IndexVector<gl::Lines> lines;
+ gl::IndexVector<gl::Triangles> triangles;
+ gl::SegmentVector<FillAttributes> lineSegments;
+ gl::SegmentVector<FillAttributes> triangleSegments;
optional<gl::VertexBuffer<FillVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Line>> lineIndexBuffer;
- optional<gl::IndexBuffer<gl::Triangle>> triangleIndexBuffer;
+ optional<gl::IndexBuffer<gl::Lines>> lineIndexBuffer;
+ optional<gl::IndexBuffer<gl::Triangles>> triangleIndexBuffer;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/frame_history.cpp b/src/mbgl/renderer/frame_history.cpp
index daf24c8c37..1ee53d87b2 100644
--- a/src/mbgl/renderer/frame_history.cpp
+++ b/src/mbgl/renderer/frame_history.cpp
@@ -1,13 +1,14 @@
#include <mbgl/renderer/frame_history.hpp>
#include <mbgl/math/minmax.hpp>
#include <mbgl/gl/context.hpp>
-#include <mbgl/gl/gl.hpp>
+
+#include <cassert>
namespace mbgl {
FrameHistory::FrameHistory() {
changeOpacities.fill(0);
- opacities.fill(0);
+ std::fill(opacities.data.get(), opacities.data.get() + opacities.bytes(), 0);
}
void FrameHistory::record(const TimePoint& now, float zoom, const Duration& duration) {
@@ -18,7 +19,7 @@ void FrameHistory::record(const TimePoint& now, float zoom, const Duration& dura
changeTimes.fill(now);
for (int16_t z = 0; z <= zoomIndex; z++) {
- opacities[z] = 255u;
+ opacities.data[z] = 255u;
}
firstFrame = false;
}
@@ -26,12 +27,12 @@ void FrameHistory::record(const TimePoint& now, float zoom, const Duration& dura
if (zoomIndex < previousZoomIndex) {
for (int16_t z = zoomIndex + 1; z <= previousZoomIndex; z++) {
changeTimes[z] = now;
- changeOpacities[z] = opacities[z];
+ changeOpacities[z] = opacities.data[z];
}
} else {
for (int16_t z = zoomIndex; z > previousZoomIndex; z--) {
changeTimes[z] = now;
- changeOpacities[z] = opacities[z];
+ changeOpacities[z] = opacities.data[z];
}
}
@@ -39,13 +40,13 @@ void FrameHistory::record(const TimePoint& now, float zoom, const Duration& dura
std::chrono::duration<float> timeDiff = now - changeTimes[z];
int32_t opacityChange = (duration == Milliseconds(0) ? 1 : (timeDiff / duration)) * 255;
if (z <= zoomIndex) {
- opacities[z] = util::min(255, changeOpacities[z] + opacityChange);
+ opacities.data[z] = util::min(255, changeOpacities[z] + opacityChange);
} else {
- opacities[z] = util::max(0, changeOpacities[z] - opacityChange);
+ opacities.data[z] = util::max(0, changeOpacities[z] - opacityChange);
}
}
- changed = true;
+ dirty = true;
if (zoomIndex != previousZoomIndex) {
previousZoomIndex = zoomIndex;
@@ -60,58 +61,17 @@ bool FrameHistory::needsAnimation(const Duration& duration) const {
}
void FrameHistory::upload(gl::Context& context, uint32_t unit) {
-
- if (changed) {
- const bool first = !texture;
- bind(context, unit);
-
- if (first) {
- MBGL_CHECK_ERROR(glTexImage2D(
- GL_TEXTURE_2D, // GLenum target
- 0, // GLint level
- GL_ALPHA, // GLint internalformat
- width, // GLsizei width
- height, // GLsizei height
- 0, // GLint border
- GL_ALPHA, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- opacities.data()
- ));
- } else {
- MBGL_CHECK_ERROR(glTexSubImage2D(
- GL_TEXTURE_2D, // GLenum target
- 0, // GLint level
- 0, // GLint xoffset
- 0, // GLint yoffset
- width, // GLsizei width
- height, // GLsizei height
- GL_ALPHA, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- opacities.data()
- ));
- }
-
- changed = false;
-
+ if (!texture) {
+ texture = context.createTexture(opacities, unit);
+ } else if (dirty) {
+ context.updateTexture(*texture, opacities, unit);
}
+ dirty = false;
}
void FrameHistory::bind(gl::Context& context, uint32_t unit) {
- if (!texture) {
- texture = context.createTexture();
- context.activeTexture = unit;
- context.texture[unit] = *texture;
-#if not MBGL_USE_GLES2
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
-#endif
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
- } else if (context.texture[unit] != *texture) {
- context.activeTexture = unit;
- context.texture[unit] = *texture;
- }
+ upload(context, unit);
+ context.bindTexture(*texture, unit);
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/frame_history.hpp b/src/mbgl/renderer/frame_history.hpp
index 063930af26..fffbd113ed 100644
--- a/src/mbgl/renderer/frame_history.hpp
+++ b/src/mbgl/renderer/frame_history.hpp
@@ -2,9 +2,10 @@
#include <array>
-#include <mbgl/platform/platform.hpp>
-#include <mbgl/gl/object.hpp>
+#include <mbgl/util/platform.hpp>
+#include <mbgl/gl/texture.hpp>
#include <mbgl/util/chrono.hpp>
+#include <mbgl/util/image.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
@@ -23,20 +24,17 @@ public:
void upload(gl::Context&, uint32_t);
private:
- const int width = 256;
- const int height = 1;
-
std::array<TimePoint, 256> changeTimes;
std::array<uint8_t, 256> changeOpacities;
- std::array<uint8_t, 256> opacities;
+ const AlphaImage opacities{ { 256, 1 } };
int16_t previousZoomIndex = 0;
- TimePoint previousTime = TimePoint::min();
- TimePoint time = TimePoint::min();
+ TimePoint previousTime;
+ TimePoint time;
bool firstFrame = true;
- bool changed = true;
+ bool dirty = true;
- mbgl::optional<gl::UniqueTexture> texture;
+ mbgl::optional<gl::Texture> texture;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp
index 7a5309bafc..007060bd1b 100644
--- a/src/mbgl/renderer/line_bucket.cpp
+++ b/src/mbgl/renderer/line_bucket.cpp
@@ -1,12 +1,8 @@
#include <mbgl/renderer/line_bucket.hpp>
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/renderer/painter.hpp>
-#include <mbgl/shader/line_shader.hpp>
-#include <mbgl/shader/line_sdf_shader.hpp>
-#include <mbgl/shader/line_pattern_shader.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/constants.hpp>
-#include <mbgl/gl/gl.hpp>
#include <cassert>
@@ -54,8 +50,8 @@ const float LINE_DISTANCE_SCALE = 1.0 / 2.0;
const float MAX_LINE_DISTANCE = std::pow(2, LINE_DISTANCE_BUFFER_BITS) / LINE_DISTANCE_SCALE;
void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
- const GLsizei len = [&coordinates] {
- GLsizei l = static_cast<GLsizei>(coordinates.size());
+ const std::size_t len = [&coordinates] {
+ std::size_t l = coordinates.size();
// If the line has duplicate vertices at the end, adjust length to remove them.
while (l > 2 && coordinates[l - 1] == coordinates[l - 2]) {
l--;
@@ -68,7 +64,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
return;
}
- const float miterLimit = layout.lineJoin == LineJoinType::Bevel ? 1.05f : float(layout.lineMiterLimit);
+ const float miterLimit = layout.get<LineJoin>() == LineJoinType::Bevel ? 1.05f : float(layout.get<LineMiterLimit>());
const double sharpCornerOffset = SHARP_CORNER_OFFSET * (float(util::EXTENT) / (util::tileSize * overscaling));
@@ -81,8 +77,8 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
return;
}
- const LineCapType beginCap = layout.lineCap;
- const LineCapType endCap = closed ? LineCapType::Butt : LineCapType(layout.lineCap);
+ const LineCapType beginCap = layout.get<LineCap>();
+ const LineCapType endCap = closed ? LineCapType::Butt : LineCapType(layout.get<LineCap>());
double distance = 0;
bool startOfLine = true;
@@ -100,10 +96,10 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
nextNormal = util::perp(util::unit(convertPoint<double>(firstCoordinate - *currentCoordinate)));
}
- const std::size_t startVertex = vertices.size();
+ const std::size_t startVertex = vertices.vertexSize();
std::vector<TriangleElement> triangleStore;
- for (GLsizei i = 0; i < len; ++i) {
+ for (std::size_t i = 0; i < len; ++i) {
if (closed && i == len - 1) {
// if the line is closed, we treat the last vertex like the first
nextCoordinate = coordinates[1];
@@ -175,12 +171,12 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
// The join if a middle vertex, otherwise the cap
const bool middleVertex = prevCoordinate && nextCoordinate;
- LineJoinType currentJoin = layout.lineJoin;
+ LineJoinType currentJoin = layout.get<LineJoin>();
const LineCapType currentCap = nextCoordinate ? beginCap : endCap;
if (middleVertex) {
if (currentJoin == LineJoinType::Round) {
- if (miterLength < layout.lineRoundLimit) {
+ if (miterLength < layout.get<LineRoundLimit>()) {
currentJoin = LineJoinType::Miter;
} else if (miterLength <= 2) {
currentJoin = LineJoinType::FakeRound;
@@ -349,25 +345,23 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
startOfLine = false;
}
- const std::size_t endVertex = vertices.size();
+ const std::size_t endVertex = vertices.vertexSize();
const std::size_t vertexCount = endVertex - startVertex;
- if (groups.empty() || groups.back().vertexLength + vertexCount > 65535) {
- // Move to a new group because the old one can't hold the geometry.
- groups.emplace_back();
+ if (segments.empty() || segments.back().vertexLength + vertexCount > std::numeric_limits<uint16_t>::max()) {
+ segments.emplace_back(startVertex, triangles.indexSize());
}
- auto& group = groups.back();
- uint16_t index = group.vertexLength;
+ auto& segment = segments.back();
+ assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
+ uint16_t index = segment.vertexLength;
for (const auto& triangle : triangleStore) {
- triangles.emplace_back(static_cast<uint16_t>(index + triangle.a),
- static_cast<uint16_t>(index + triangle.b),
- static_cast<uint16_t>(index + triangle.c));
+ triangles.emplace_back(index + triangle.a, index + triangle.b, index + triangle.c);
}
- group.vertexLength += vertexCount;
- group.indexLength += triangleStore.size();
+ segment.vertexLength += vertexCount;
+ segment.indexLength += triangleStore.size() * 3;
}
void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate,
@@ -378,13 +372,11 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate,
bool round,
std::size_t startVertex,
std::vector<TriangleElement>& triangleStore) {
- int8_t tx = round ? 1 : 0;
-
Point<double> extrude = normal;
if (endLeft)
extrude = extrude - (util::perp(normal) * endLeft);
- vertices.emplace_back(currentCoordinate.x, currentCoordinate.y, extrude.x, extrude.y, tx, 0, endLeft, distance * LINE_DISTANCE_SCALE);
- e3 = vertices.size() - 1 - startVertex;
+ vertices.emplace_back(LineAttributes::vertex(currentCoordinate, extrude, { round, false }, endLeft, distance * LINE_DISTANCE_SCALE));
+ e3 = vertices.vertexSize() - 1 - startVertex;
if (e1 >= 0 && e2 >= 0) {
triangleStore.emplace_back(e1, e2, e3);
}
@@ -394,8 +386,8 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate,
extrude = normal * -1.0;
if (endRight)
extrude = extrude - (util::perp(normal) * endRight);
- vertices.emplace_back(currentCoordinate.x, currentCoordinate.y, extrude.x, extrude.y, tx, 1, -endRight, distance * LINE_DISTANCE_SCALE);
- e3 = vertices.size() - 1 - startVertex;
+ vertices.emplace_back(LineAttributes::vertex(currentCoordinate, extrude, { round, true }, -endRight, distance * LINE_DISTANCE_SCALE));
+ e3 = vertices.vertexSize() - 1 - startVertex;
if (e1 >= 0 && e2 >= 0) {
triangleStore.emplace_back(e1, e2, e3);
}
@@ -418,11 +410,9 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex,
bool lineTurnsLeft,
std::size_t startVertex,
std::vector<TriangleElement>& triangleStore) {
- int8_t ty = lineTurnsLeft;
-
Point<double> flippedExtrude = extrude * (lineTurnsLeft ? -1.0 : 1.0);
- vertices.emplace_back(currentVertex.x, currentVertex.y, flippedExtrude.x, flippedExtrude.y, 0, ty, 0, distance * LINE_DISTANCE_SCALE);
- e3 = vertices.size() - 1 - startVertex;
+ vertices.emplace_back(LineAttributes::vertex(currentVertex, flippedExtrude, { false, lineTurnsLeft }, 0, distance * LINE_DISTANCE_SCALE));
+ e3 = vertices.vertexSize() - 1 - startVertex;
if (e1 >= 0 && e2 >= 0) {
triangleStore.emplace_back(e1, e2, e3);
}
@@ -450,65 +440,7 @@ void LineBucket::render(Painter& painter,
}
bool LineBucket::hasData() const {
- return !groups.empty();
-}
-
-bool LineBucket::needsClipping() const {
- return true;
-}
-
-void LineBucket::drawLines(LineShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : groups) {
- if (!group.indexLength) {
- continue;
- }
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *indexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * indexBuffer->primitiveSize;
- }
-}
-
-void LineBucket::drawLineSDF(LineSDFShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : groups) {
- if (!group.indexLength) {
- continue;
- }
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *indexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * indexBuffer->primitiveSize;
- }
-}
-
-void LineBucket::drawLinePatterns(LinePatternShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET(0);
- GLbyte* elements_index = BUFFER_OFFSET(0);
- for (auto& group : groups) {
- if (!group.indexLength) {
- continue;
- }
- group.getVAO(shader, paintMode).bind(
- shader, *vertexBuffer, *indexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * vertexBuffer->vertexSize;
- elements_index += group.indexLength * indexBuffer->primitiveSize;
- }
+ return !segments.empty();
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp
index 14af710877..d11d78ff69 100644
--- a/src/mbgl/renderer/line_bucket.hpp
+++ b/src/mbgl/renderer/line_bucket.hpp
@@ -1,23 +1,18 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/renderer/element_group.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/gl/index_buffer.hpp>
-#include <mbgl/shader/line_vertex.hpp>
+#include <mbgl/gl/segment.hpp>
+#include <mbgl/programs/line_program.hpp>
#include <mbgl/style/layers/line_layer_properties.hpp>
#include <vector>
namespace mbgl {
-class LineShader;
-class LineSDFShader;
-class LinePatternShader;
-
class LineBucket : public Bucket {
-
public:
LineBucket(uint32_t overscaling);
~LineBucket() override;
@@ -25,14 +20,18 @@ public:
void upload(gl::Context&) override;
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;
bool hasData() const override;
- bool needsClipping() const override;
void addGeometry(const GeometryCollection&);
void addGeometry(const GeometryCoordinates& line);
- void drawLines(LineShader&, gl::Context&, PaintMode);
- void drawLineSDF(LineSDFShader&, gl::Context&, PaintMode);
- void drawLinePatterns(LinePatternShader&, gl::Context&, PaintMode);
+ style::LineLayoutProperties::Evaluated layout;
+
+ gl::VertexVector<LineVertex> vertices;
+ gl::IndexVector<gl::Triangles> triangles;
+ gl::SegmentVector<LineAttributes> segments;
+
+ optional<gl::VertexBuffer<LineVertex>> vertexBuffer;
+ optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
private:
struct TriangleElement {
@@ -46,18 +45,6 @@ private:
const Point<double>& extrude, bool lineTurnsLeft, std::size_t startVertex,
std::vector<TriangleElement>& triangleStore);
-public:
- style::LineLayoutProperties layout;
-
-private:
- std::vector<LineVertex> vertices;
- std::vector<gl::Triangle> triangles;
-
- std::vector<ElementGroup<LineShader, LineSDFShader, LinePatternShader>> groups;
-
- optional<gl::VertexBuffer<LineVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
-
std::ptrdiff_t e1;
std::ptrdiff_t e2;
std::ptrdiff_t e3;
diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp
index bd67dc9cfd..213c01cfbd 100644
--- a/src/mbgl/renderer/paint_parameters.hpp
+++ b/src/mbgl/renderer/paint_parameters.hpp
@@ -2,12 +2,12 @@
namespace mbgl {
-class Shaders;
+class Programs;
class View;
class PaintParameters {
public:
- Shaders& shaders;
+ Programs& programs;
View& view;
};
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index fc61d6e0a0..5894912ef3 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -7,8 +7,7 @@
#include <mbgl/map/view.hpp>
-#include <mbgl/platform/log.hpp>
-#include <mbgl/gl/gl.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/gl/debugging.hpp>
#include <mbgl/style/style.hpp>
@@ -22,7 +21,8 @@
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/text/glyph_atlas.hpp>
-#include <mbgl/shader/shaders.hpp>
+#include <mbgl/programs/program_parameters.hpp>
+#include <mbgl/programs/programs.hpp>
#include <mbgl/algorithm/generate_clip_ids.hpp>
#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
@@ -42,37 +42,63 @@ namespace mbgl {
using namespace style;
-Painter::Painter(gl::Context& context_, const TransformState& state_)
+static gl::VertexVector<FillVertex> tileVertices() {
+ gl::VertexVector<FillVertex> result;
+ result.emplace_back(FillAttributes::vertex({ 0, 0 }));
+ result.emplace_back(FillAttributes::vertex({ util::EXTENT, 0 }));
+ result.emplace_back(FillAttributes::vertex({ 0, util::EXTENT }));
+ result.emplace_back(FillAttributes::vertex({ util::EXTENT, util::EXTENT }));
+ return result;
+}
+
+static gl::IndexVector<gl::Triangles> tileTriangleIndices() {
+ gl::IndexVector<gl::Triangles> result;
+ result.emplace_back(0, 1, 2);
+ result.emplace_back(1, 2, 3);
+ return result;
+}
+
+static gl::IndexVector<gl::LineStrip> tileLineStripIndices() {
+ gl::IndexVector<gl::LineStrip> result;
+ result.emplace_back(0);
+ result.emplace_back(1);
+ result.emplace_back(3);
+ result.emplace_back(2);
+ result.emplace_back(0);
+ return result;
+}
+
+static gl::VertexVector<RasterVertex> rasterVertices() {
+ gl::VertexVector<RasterVertex> result;
+ result.emplace_back(RasterProgram::vertex({ 0, 0 }, { 0, 0 }));
+ result.emplace_back(RasterProgram::vertex({ util::EXTENT, 0 }, { 32767, 0 }));
+ result.emplace_back(RasterProgram::vertex({ 0, util::EXTENT }, { 0, 32767 }));
+ result.emplace_back(RasterProgram::vertex({ util::EXTENT, util::EXTENT }, { 32767, 32767 }));
+ return result;
+}
+
+Painter::Painter(gl::Context& context_, const TransformState& state_, float pixelRatio)
: context(context_),
state(state_),
- tileTriangleVertexBuffer(context.createVertexBuffer(std::vector<FillVertex> {{
- { 0, 0 },
- { util::EXTENT, 0 },
- { 0, util::EXTENT },
- { util::EXTENT, 0 },
- { 0, util::EXTENT },
- { util::EXTENT, util::EXTENT }
- }})),
- tileLineStripVertexBuffer(context.createVertexBuffer(std::vector<FillVertex> {{
- { 0, 0 },
- { util::EXTENT, 0 },
- { util::EXTENT, util::EXTENT },
- { 0, util::EXTENT },
- { 0, 0 }
- }})),
- rasterVertexBuffer(context.createVertexBuffer(std::vector<RasterVertex> {{
- { 0, 0, 0, 0 },
- { util::EXTENT, 0, 32767, 0 },
- { 0, util::EXTENT, 0, 32767 },
- { util::EXTENT, util::EXTENT, 32767, 32767 }
- }})) {
+ tileVertexBuffer(context.createVertexBuffer(tileVertices())),
+ rasterVertexBuffer(context.createVertexBuffer(rasterVertices())),
+ tileTriangleIndexBuffer(context.createIndexBuffer(tileTriangleIndices())),
+ tileBorderIndexBuffer(context.createIndexBuffer(tileLineStripIndices())) {
+
+ tileTriangleSegments.emplace_back(0, 0, 4, 6);
+ tileBorderSegments.emplace_back(0, 0, 4, 5);
+ rasterSegments.emplace_back(0, 0, 4, 6);
+
#ifndef NDEBUG
gl::debugging::enable();
#endif
- shaders = std::make_unique<Shaders>(context);
+ ProgramParameters programParameters{ pixelRatio, false };
+ programs = std::make_unique<Programs>(context, programParameters);
#ifndef NDEBUG
- overdrawShaders = std::make_unique<Shaders>(context, gl::Shader::Overdraw);
+
+ ProgramParameters programParametersOverdraw{ pixelRatio, true };
+ overdrawPrograms = std::make_unique<Programs>(context, programParametersOverdraw);
#endif
}
@@ -82,12 +108,6 @@ bool Painter::needsAnimation() const {
return frameHistory.needsAnimation(util::DEFAULT_FADE_DURATION);
}
-void Painter::setClipping(const ClipID& clip) {
- const GLint ref = (GLint)clip.reference.to_ulong();
- const GLuint mask = (GLuint)clip.mask.to_ulong();
- context.stencilFunc = { gl::StencilTestFunction::Equal, ref, mask };
-}
-
void Painter::cleanup() {
context.performCleanup();
}
@@ -100,9 +120,9 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
PaintParameters parameters {
#ifndef NDEBUG
- paintMode() == PaintMode::Overdraw ? *overdrawShaders : *shaders,
+ paintMode() == PaintMode::Overdraw ? *overdrawPrograms : *programs,
#else
- *shaders,
+ *programs,
#endif
view
};
@@ -111,15 +131,14 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
spriteAtlas = style.spriteAtlas.get();
lineAtlas = style.lineAtlas.get();
- RenderData renderData = style.getRenderData(frame.debugOptions);
+ RenderData renderData = style.getRenderData(frame.debugOptions, state.getAngle());
const std::vector<RenderItem>& order = renderData.order;
const std::unordered_set<Source*>& sources = renderData.sources;
- const Color& background = renderData.backgroundColor;
// Update the default matrices to the current viewport dimensions.
state.getProjMatrix(projMatrix);
- pixelsToGLUnits = {{ 2.0f / state.getWidth(), -2.0f / state.getHeight() }};
+ pixelsToGLUnits = {{ 2.0f / state.getSize().width, -2.0f / state.getSize().height }};
if (state.getViewportMode() == ViewportMode::FlippedY) {
pixelsToGLUnits[1] *= -1;
}
@@ -153,26 +172,11 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
{
MBGL_DEBUG_GROUP("clear");
view.bind();
- context.stencilFunc = { gl::StencilTestFunction::Always, 0, ~0u };
- context.stencilTest = true;
- context.stencilMask = 0xFF;
- context.depthTest = false;
- context.depthMask = true;
- context.colorMask = { true, true, true, true };
-
- if (paintMode() == PaintMode::Overdraw) {
- context.blend = true;
- context.blendFunc = { gl::BlendSourceFactor::ConstantColor,
- gl::BlendDestinationFactor::One };
- const float overdraw = 1.0f / 8.0f;
- context.blendColor = { overdraw, overdraw, overdraw, 0.0f };
- context.clearColor = Color::black();
- } else {
- context.clearColor = background;
- }
- context.clearStencil = 0;
- context.clearDepth = 1;
- MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
+ context.clear(paintMode() == PaintMode::Overdraw
+ ? Color::black()
+ : renderData.backgroundColor,
+ 1.0f,
+ 0);
}
// - CLIPPING MASKS ----------------------------------------------------------------------------
@@ -186,7 +190,12 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
source->baseImpl->startRender(generator, projMatrix, state);
}
- drawClippingMasks(parameters, generator.getStencils());
+ MBGL_DEBUG_GROUP("clipping masks");
+
+ for (const auto& stencil : generator.getStencils()) {
+ MBGL_DEBUG_GROUP(std::string{ "mask: " } + util::toString(stencil.first));
+ renderClippingMask(stencil.first, stencil.second);
+ }
}
#if not MBGL_USE_GLES2 and not defined(NDEBUG)
@@ -214,7 +223,7 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
renderPass(parameters,
RenderPass::Translucent,
order.begin(), order.end(),
- static_cast<GLsizei>(order.size()) - 1, -1);
+ static_cast<uint32_t>(order.size()) - 1, -1);
if (debug::renderTree) { Log::Info(Event::Render, "}"); indent--; }
@@ -275,19 +284,6 @@ void Painter::renderPass(PaintParameters& parameters,
if (!layer.baseImpl->hasRenderPass(pass))
continue;
- if (paintMode() == PaintMode::Overdraw) {
- context.blend = true;
- } else if (pass == RenderPass::Translucent) {
- context.blend = true;
- context.blendFunc = { gl::BlendSourceFactor::One,
- gl::BlendDestinationFactor::OneMinusSrcAlpha };
- } else {
- context.blend = false;
- }
-
- context.colorMask = { true, true, true, true };
- context.stencilMask = 0x0;
-
if (layer.is<BackgroundLayer>()) {
MBGL_DEBUG_GROUP("background");
renderBackground(parameters, *layer.as<BackgroundLayer>());
@@ -296,11 +292,9 @@ void Painter::renderPass(PaintParameters& parameters,
// Reset GL state to a known state so the CustomLayer always has a clean slate.
context.vertexArrayObject = 0;
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = false;
- context.stencilTest = false;
- setDepthSublayer(0);
+ context.setDepthMode(depthModeForSublayer(0, gl::DepthMode::ReadOnly));
+ context.setStencilMode(gl::StencilMode::disabled());
+ context.setColorMode(colorModeForRenderPass());
layer.as<CustomLayer>()->impl->render(state);
@@ -310,9 +304,6 @@ void Painter::renderPass(PaintParameters& parameters,
context.setDirtyState();
} else {
MBGL_DEBUG_GROUP(layer.baseImpl->id + " - " + util::toString(item.tile->id));
- if (item.bucket->needsClipping()) {
- setClipping(item.tile->clip);
- }
item.bucket->render(*this, parameters, layer, *item.tile);
}
}
@@ -322,10 +313,46 @@ void Painter::renderPass(PaintParameters& parameters,
}
}
-void Painter::setDepthSublayer(int n) {
+mat4 Painter::matrixForTile(const UnwrappedTileID& tileID) {
+ mat4 matrix;
+ state.matrixFor(matrix, tileID);
+ matrix::multiply(matrix, projMatrix, matrix);
+ return matrix;
+}
+
+gl::DepthMode Painter::depthModeForSublayer(uint8_t n, gl::DepthMode::Mask mask) const {
float nearDepth = ((1 + currentLayer) * numSublayers + n) * depthEpsilon;
float farDepth = nearDepth + depthRangeSize;
- context.depthRange = { nearDepth, farDepth };
+ return gl::DepthMode { gl::DepthMode::LessEqual, mask, { nearDepth, farDepth } };
+}
+
+gl::StencilMode Painter::stencilModeForClipping(const ClipID& id) const {
+ return gl::StencilMode {
+ gl::StencilMode::Equal { static_cast<uint32_t>(id.mask.to_ulong()) },
+ static_cast<int32_t>(id.reference.to_ulong()),
+ 0,
+ gl::StencilMode::Keep,
+ gl::StencilMode::Keep,
+ gl::StencilMode::Replace
+ };
+}
+
+gl::ColorMode Painter::colorModeForRenderPass() const {
+ if (paintMode() == PaintMode::Overdraw) {
+ const float overdraw = 1.0f / 8.0f;
+ return gl::ColorMode {
+ gl::ColorMode::Add {
+ gl::ColorMode::ConstantColor,
+ gl::ColorMode::One
+ },
+ Color { overdraw, overdraw, overdraw, 0.0f },
+ gl::ColorMode::Mask { true, true, true, true }
+ };
+ } else if (pass == RenderPass::Translucent) {
+ return gl::ColorMode::alphaBlended();
+ } else {
+ return gl::ColorMode::unblended();
+ }
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp
index f339ed1aed..dec7fa57fd 100644
--- a/src/mbgl/renderer/painter.hpp
+++ b/src/mbgl/renderer/painter.hpp
@@ -8,10 +8,11 @@
#include <mbgl/renderer/render_item.hpp>
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/gl/vao.hpp>
#include <mbgl/gl/context.hpp>
-#include <mbgl/shader/fill_vertex.hpp>
-#include <mbgl/shader/raster_vertex.hpp>
+#include <mbgl/programs/debug_program.hpp>
+#include <mbgl/programs/program_parameters.hpp>
+#include <mbgl/programs/fill_program.hpp>
+#include <mbgl/programs/raster_program.hpp>
#include <mbgl/style/style.hpp>
@@ -41,8 +42,7 @@ class CircleBucket;
class SymbolBucket;
class RasterBucket;
-class Shaders;
-class SymbolSDFShader;
+class Programs;
class PaintParameters;
struct ClipID;
@@ -68,7 +68,7 @@ struct FrameData {
class Painter : private util::noncopyable {
public:
- Painter(gl::Context&, const TransformState&);
+ Painter(gl::Context&, const TransformState&, float pixelRatio);
~Painter();
void render(const style::Style&,
@@ -78,20 +78,8 @@ public:
void cleanup();
- // Renders debug information for a tile.
+ void renderClippingMask(const UnwrappedTileID&, const ClipID&);
void renderTileDebug(const RenderTile&);
-
- // Renders the red debug frame around a tile, visualizing its perimeter.
- void renderDebugFrame(const mat4 &matrix);
-
-#ifndef NDEBUG
- // Renders tile clip boundaries, using stencil buffer to calculate fill color.
- void renderClipMasks(PaintParameters&);
- // Renders the depth buffer.
- void renderDepthBuffer(PaintParameters&);
-#endif
-
- void renderDebugText(Tile&, const mat4&);
void renderFill(PaintParameters&, FillBucket&, const style::FillLayer&, const RenderTile&);
void renderLine(PaintParameters&, LineBucket&, const style::LineLayer&, const RenderTile&);
void renderCircle(PaintParameters&, CircleBucket&, const style::CircleLayer&, const RenderTile&);
@@ -99,11 +87,12 @@ public:
void renderRaster(PaintParameters&, RasterBucket&, const style::RasterLayer&, const RenderTile&);
void renderBackground(PaintParameters&, const style::BackgroundLayer&);
- float saturationFactor(float saturation);
- float contrastFactor(float contrast);
- std::array<float, 3> spinWeights(float spin_value);
-
- void drawClippingMasks(PaintParameters&, const std::map<UnwrappedTileID, ClipID>&);
+#ifndef NDEBUG
+ // Renders tile clip boundaries, using stencil buffer to calculate fill color.
+ void renderClipMasks(PaintParameters&);
+ // Renders the depth buffer.
+ void renderDepthBuffer(PaintParameters&);
+#endif
bool needsAnimation() const;
@@ -116,31 +105,10 @@ private:
Iterator it, Iterator end,
uint32_t i, int8_t increment);
- void setClipping(const ClipID&);
-
- void renderSDF(SymbolBucket&,
- const RenderTile&,
- float scaleDivisor,
- std::array<float, 2> texsize,
- SymbolSDFShader& sdfShader,
- void (SymbolBucket::*drawSDF)(SymbolSDFShader&, gl::Context&, PaintMode),
-
- // Layout
- style::AlignmentType rotationAlignment,
- style::AlignmentType pitchAlignment,
- float layoutSize,
-
- // Paint
- float opacity,
- Color color,
- Color haloColor,
- float haloWidth,
- float haloBlur,
- std::array<float, 2> translate,
- style::TranslateAnchorType translateAnchor,
- float paintSize);
-
- void setDepthSublayer(int n);
+ mat4 matrixForTile(const UnwrappedTileID&);
+ gl::DepthMode depthModeForSublayer(uint8_t n, gl::DepthMode::Mask) const;
+ gl::StencilMode stencilModeForClipping(const ClipID&) const;
+ gl::ColorMode colorModeForRenderPass() const;
#ifndef NDEBUG
PaintMode paintMode() const {
@@ -185,16 +153,20 @@ private:
FrameHistory frameHistory;
- std::unique_ptr<Shaders> shaders;
+ std::unique_ptr<Programs> programs;
#ifndef NDEBUG
- std::unique_ptr<Shaders> overdrawShaders;
+ std::unique_ptr<Programs> overdrawPrograms;
#endif
- gl::VertexBuffer<FillVertex> tileTriangleVertexBuffer;
- gl::VertexBuffer<FillVertex> tileLineStripVertexBuffer;
+ gl::VertexBuffer<FillVertex> tileVertexBuffer;
gl::VertexBuffer<RasterVertex> rasterVertexBuffer;
- gl::VertexArrayObject tileBorderArray;
+ gl::IndexBuffer<gl::Triangles> tileTriangleIndexBuffer;
+ gl::IndexBuffer<gl::LineStrip> tileBorderIndexBuffer;
+
+ gl::SegmentVector<FillAttributes> tileTriangleSegments;
+ gl::SegmentVector<DebugAttributes> tileBorderSegments;
+ gl::SegmentVector<RasterAttributes> rasterSegments;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_background.cpp b/src/mbgl/renderer/painter_background.cpp
index 61ec76d1d8..4a3e41701d 100644
--- a/src/mbgl/renderer/painter_background.cpp
+++ b/src/mbgl/renderer/painter_background.cpp
@@ -1,12 +1,10 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
-#include <mbgl/gl/gl.hpp>
-
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/background_layer_impl.hpp>
-#include <mbgl/shader/shaders.hpp>
+#include <mbgl/programs/programs.hpp>
+#include <mbgl/programs/fill_program.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
-#include <mbgl/util/mat4.hpp>
#include <mbgl/util/tile_cover.hpp>
namespace mbgl {
@@ -16,75 +14,61 @@ using namespace style;
void Painter::renderBackground(PaintParameters& parameters, const BackgroundLayer& layer) {
// Note that for bottommost layers without a pattern, the background color is drawn with
// glClear rather than this method.
- const BackgroundPaintProperties& properties = layer.impl->paint;
-
- bool isPatterned = !properties.backgroundPattern.value.to.empty();// && false;
- optional<SpriteAtlasPosition> imagePosA;
- optional<SpriteAtlasPosition> imagePosB;
-
- auto& patternShader = parameters.shaders.fillPattern;
- auto& plainShader = parameters.shaders.fill;
- auto& arrayBackgroundPattern = parameters.shaders.backgroundPatternArray;
- auto& arrayBackground = parameters.shaders.backgroundArray;
+ const BackgroundPaintProperties::Evaluated& properties = layer.impl->paint.evaluated;
- if (isPatterned) {
- imagePosA = spriteAtlas->getPosition(properties.backgroundPattern.value.from,
- SpritePatternMode::Repeating);
- imagePosB = spriteAtlas->getPosition(properties.backgroundPattern.value.to,
- SpritePatternMode::Repeating);
+ if (!properties.get<BackgroundPattern>().to.empty()) {
+ optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(
+ properties.get<BackgroundPattern>().from, SpritePatternMode::Repeating);
+ optional<SpriteAtlasPosition> imagePosB = spriteAtlas->getPosition(
+ properties.get<BackgroundPattern>().to, SpritePatternMode::Repeating);
if (!imagePosA || !imagePosB)
return;
- context.program = patternShader.getID();
- patternShader.u_matrix = identityMatrix;
- patternShader.u_pattern_tl_a = imagePosA->tl;
- patternShader.u_pattern_br_a = imagePosA->br;
- patternShader.u_pattern_tl_b = imagePosB->tl;
- patternShader.u_pattern_br_b = imagePosB->br;
- patternShader.u_mix = properties.backgroundPattern.value.t;
- patternShader.u_opacity = properties.backgroundOpacity;
-
spriteAtlas->bind(true, context, 0);
- arrayBackgroundPattern.bind(patternShader, tileTriangleVertexBuffer, BUFFER_OFFSET(0), context);
+ for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) {
+ parameters.programs.fillPattern.draw(
+ context,
+ gl::Triangles(),
+ depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ FillPatternUniforms::values(
+ matrixForTile(tileID),
+ properties.get<BackgroundOpacity>(),
+ context.viewport.getCurrentValue().size,
+ *imagePosA,
+ *imagePosB,
+ properties.get<BackgroundPattern>(),
+ tileID,
+ state
+ ),
+ tileVertexBuffer,
+ tileTriangleIndexBuffer,
+ tileTriangleSegments
+ );
+ }
} else {
- context.program = plainShader.getID();
- plainShader.u_color = properties.backgroundColor;
- plainShader.u_opacity = properties.backgroundOpacity;
-
- arrayBackground.bind(plainShader, tileTriangleVertexBuffer, BUFFER_OFFSET(0), context);
- }
-
- context.stencilTest = false;
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = false;
- setDepthSublayer(0);
-
- for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) {
- mat4 vertexMatrix;
- state.matrixFor(vertexMatrix, tileID);
- matrix::multiply(vertexMatrix, projMatrix, vertexMatrix);
-
- if (isPatterned) {
- patternShader.u_matrix = vertexMatrix;
- patternShader.u_pattern_size_a = imagePosA->size;
- patternShader.u_pattern_size_b = imagePosB->size;
- patternShader.u_scale_a = properties.backgroundPattern.value.fromScale;
- patternShader.u_scale_b = properties.backgroundPattern.value.toScale;
- patternShader.u_tile_units_to_pixels = 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom());
-
- GLint tileSizeAtNearestZoom = util::tileSize * state.zoomScale(state.getIntegerZoom() - tileID.canonical.z);
- GLint pixelX = tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * state.zoomScale(tileID.canonical.z));
- GLint pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
- patternShader.u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
- patternShader.u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
- } else {
- plainShader.u_matrix = vertexMatrix;
+ for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) {
+ parameters.programs.fill.draw(
+ context,
+ gl::Triangles(),
+ depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ FillProgram::UniformValues {
+ uniforms::u_matrix::Value{ matrixForTile(tileID) },
+ uniforms::u_opacity::Value{ properties.get<BackgroundOpacity>() },
+ uniforms::u_color::Value{ properties.get<BackgroundColor>() },
+ uniforms::u_outline_color::Value{ properties.get<BackgroundColor>() },
+ uniforms::u_world::Value{ context.viewport.getCurrentValue().size },
+ },
+ tileVertexBuffer,
+ tileTriangleIndexBuffer,
+ tileTriangleSegments
+ );
}
-
- MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, static_cast<GLsizei>(tileTriangleVertexBuffer.vertexCount)));
}
}
diff --git a/src/mbgl/renderer/painter_circle.cpp b/src/mbgl/renderer/painter_circle.cpp
index 462ed59ebf..966d58b59b 100644
--- a/src/mbgl/renderer/painter_circle.cpp
+++ b/src/mbgl/renderer/painter_circle.cpp
@@ -2,11 +2,11 @@
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/circle_bucket.hpp>
#include <mbgl/renderer/render_tile.hpp>
-
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/circle_layer_impl.hpp>
-
-#include <mbgl/shader/shaders.hpp>
+#include <mbgl/programs/programs.hpp>
+#include <mbgl/programs/circle_program.hpp>
+#include <mbgl/gl/context.hpp>
namespace mbgl {
@@ -16,42 +16,46 @@ void Painter::renderCircle(PaintParameters& parameters,
CircleBucket& bucket,
const CircleLayer& layer,
const RenderTile& tile) {
- // Abort early.
- if (pass == RenderPass::Opaque) return;
-
- context.stencilTest = frame.mapMode == MapMode::Still;
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = false;
- setDepthSublayer(0);
-
- const CirclePaintProperties& properties = layer.impl->paint;
- auto& circleShader = parameters.shaders.circle;
-
- context.program = circleShader.getID();
-
- circleShader.u_matrix = tile.translatedMatrix(properties.circleTranslate,
- properties.circleTranslateAnchor,
- state);
-
- if (properties.circlePitchScale == CirclePitchScaleType::Map) {
- circleShader.u_extrude_scale = {{
- pixelsToGLUnits[0] * state.getAltitude(),
- pixelsToGLUnits[1] * state.getAltitude()
- }};
- circleShader.u_scale_with_map = true;
- } else {
- circleShader.u_extrude_scale = pixelsToGLUnits;
- circleShader.u_scale_with_map = false;
+ if (pass == RenderPass::Opaque) {
+ return;
}
- circleShader.u_devicepixelratio = frame.pixelRatio;
- circleShader.u_color = properties.circleColor;
- circleShader.u_radius = properties.circleRadius;
- circleShader.u_blur = properties.circleBlur;
- circleShader.u_opacity = properties.circleOpacity;
-
- bucket.drawCircles(circleShader, context, paintMode());
+ const CirclePaintProperties::Evaluated& properties = layer.impl->paint.evaluated;
+ const bool scaleWithMap = properties.get<CirclePitchScale>() == CirclePitchScaleType::Map;
+
+ parameters.programs.circle.draw(
+ context,
+ gl::Triangles(),
+ depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ frame.mapMode == MapMode::Still
+ ? stencilModeForClipping(tile.clip)
+ : gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ CircleProgram::UniformValues {
+ uniforms::u_matrix::Value{
+ tile.translatedMatrix(properties.get<CircleTranslate>(),
+ properties.get<CircleTranslateAnchor>(),
+ state)
+ },
+ uniforms::u_opacity::Value{ properties.get<CircleOpacity>() },
+ uniforms::u_color::Value{ properties.get<CircleColor>() },
+ uniforms::u_radius::Value{ properties.get<CircleRadius>() },
+ uniforms::u_blur::Value{ properties.get<CircleBlur>() },
+ uniforms::u_stroke_color::Value{ properties.get<CircleStrokeColor>() },
+ uniforms::u_stroke_width::Value{ properties.get<CircleStrokeWidth>() },
+ uniforms::u_stroke_opacity::Value{ properties.get<CircleStrokeOpacity>() },
+ uniforms::u_scale_with_map::Value{ scaleWithMap },
+ uniforms::u_extrude_scale::Value{ scaleWithMap
+ ? std::array<float, 2> {{
+ pixelsToGLUnits[0] * state.getCameraToCenterDistance(),
+ pixelsToGLUnits[1] * state.getCameraToCenterDistance()
+ }}
+ : pixelsToGLUnits }
+ },
+ *bucket.vertexBuffer,
+ *bucket.indexBuffer,
+ bucket.segments
+ );
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_clipping.cpp b/src/mbgl/renderer/painter_clipping.cpp
index 68f580c280..a2529561fe 100644
--- a/src/mbgl/renderer/painter_clipping.cpp
+++ b/src/mbgl/renderer/painter_clipping.cpp
@@ -1,49 +1,35 @@
#include <mbgl/renderer/painter.hpp>
-#include <mbgl/renderer/paint_parameters.hpp>
-#include <mbgl/gl/gl.hpp>
-
-#include <mbgl/style/source.hpp>
-#include <mbgl/shader/shaders.hpp>
+#include <mbgl/programs/programs.hpp>
+#include <mbgl/programs/fill_program.hpp>
#include <mbgl/util/clip_id.hpp>
-#include <mbgl/util/string.hpp>
-#include <mbgl/gl/debugging.hpp>
namespace mbgl {
-
-void Painter::drawClippingMasks(PaintParameters& parameters, const std::map<UnwrappedTileID, ClipID>& stencils) {
- MBGL_DEBUG_GROUP("clipping masks");
-
- auto& plainShader = parameters.shaders.fill;
- auto& arrayCoveringPlain = parameters.shaders.coveringPlainArray;
-
- mat4 matrix;
- const GLuint mask = 0b11111111;
-
- context.program = plainShader.getID();
- context.stencilOp = { gl::StencilTestOperation::Keep, gl::StencilTestOperation::Keep,
- gl::StencilTestOperation::Replace };
- context.stencilTest = true;
- context.depthTest = false;
- context.depthMask = false;
- context.colorMask = { false, false, false, false };
- context.stencilMask = mask;
-
- arrayCoveringPlain.bind(plainShader, tileTriangleVertexBuffer, BUFFER_OFFSET_0, context);
-
- for (const auto& stencil : stencils) {
- const auto& id = stencil.first;
- const auto& clip = stencil.second;
-
- MBGL_DEBUG_GROUP(std::string{ "mask: " } + util::toString(id));
- state.matrixFor(matrix, id);
- matrix::multiply(matrix, projMatrix, matrix);
- plainShader.u_matrix = matrix;
-
- const GLint ref = (GLint)(clip.reference.to_ulong());
- context.stencilFunc = { gl::StencilTestFunction::Always, ref, mask };
- MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(tileTriangleVertexBuffer.vertexCount)));
- }
+void Painter::renderClippingMask(const UnwrappedTileID& tileID, const ClipID& clip) {
+ programs->fill.draw(
+ context,
+ gl::Triangles(),
+ gl::DepthMode::disabled(),
+ gl::StencilMode {
+ gl::StencilMode::Always(),
+ static_cast<int32_t>(clip.reference.to_ulong()),
+ 0b11111111,
+ gl::StencilMode::Keep,
+ gl::StencilMode::Keep,
+ gl::StencilMode::Replace
+ },
+ gl::ColorMode::disabled(),
+ FillProgram::UniformValues {
+ uniforms::u_matrix::Value{ matrixForTile(tileID) },
+ uniforms::u_opacity::Value{ 0.0f },
+ uniforms::u_color::Value{ Color {} },
+ uniforms::u_outline_color::Value{ Color {} },
+ uniforms::u_world::Value{ context.viewport.getCurrentValue().size },
+ },
+ tileVertexBuffer,
+ tileTriangleIndexBuffer,
+ tileTriangleSegments
+ );
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp
index e57bb2205e..2b838dec0e 100644
--- a/src/mbgl/renderer/painter_debug.cpp
+++ b/src/mbgl/renderer/painter_debug.cpp
@@ -4,161 +4,121 @@
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/map/view.hpp>
#include <mbgl/tile/tile.hpp>
-#include <mbgl/shader/shaders.hpp>
+#include <mbgl/programs/programs.hpp>
+#include <mbgl/programs/fill_program.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/gl/debugging.hpp>
-#include <mbgl/gl/gl.hpp>
#include <mbgl/util/color.hpp>
namespace mbgl {
-void Painter::renderTileDebug(const RenderTile& tile) {
- MBGL_DEBUG_GROUP(std::string { "debug " } + util::toString(tile.id));
- if (frame.debugOptions != MapDebugOptions::NoDebug) {
- setClipping(tile.clip);
- if (frame.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) {
- renderDebugText(tile.tile, tile.matrix);
+void Painter::renderTileDebug(const RenderTile& renderTile) {
+ if (frame.debugOptions == MapDebugOptions::NoDebug)
+ return;
+
+ MBGL_DEBUG_GROUP(std::string { "debug " } + util::toString(renderTile.id));
+
+ auto draw = [&] (Color color, const auto& vertexBuffer, const auto& indexBuffer, const auto& segments, auto drawMode) {
+ programs->debug.draw(
+ context,
+ drawMode,
+ gl::DepthMode::disabled(),
+ stencilModeForClipping(renderTile.clip),
+ gl::ColorMode::unblended(),
+ DebugProgram::UniformValues {
+ uniforms::u_matrix::Value{ renderTile.matrix },
+ uniforms::u_color::Value{ color }
+ },
+ vertexBuffer,
+ indexBuffer,
+ segments
+ );
+ };
+
+ if (frame.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) {
+ Tile& tile = renderTile.tile;
+ if (!tile.debugBucket || tile.debugBucket->renderable != tile.isRenderable() ||
+ tile.debugBucket->complete != tile.isComplete() ||
+ !(tile.debugBucket->modified == tile.modified) ||
+ !(tile.debugBucket->expires == tile.expires) ||
+ tile.debugBucket->debugMode != frame.debugOptions) {
+ tile.debugBucket = std::make_unique<DebugBucket>(
+ tile.id, tile.isRenderable(), tile.isComplete(), tile.modified,
+ tile.expires, frame.debugOptions, context);
}
- if (frame.debugOptions & MapDebugOptions::TileBorders) {
- renderDebugFrame(tile.matrix);
- }
- }
-}
-void Painter::renderDebugText(Tile& tile, const mat4 &matrix) {
- MBGL_DEBUG_GROUP("debug text");
-
- context.depthTest = false;
-
- if (!tile.debugBucket || tile.debugBucket->renderable != tile.isRenderable() ||
- tile.debugBucket->complete != tile.isComplete() ||
- !(tile.debugBucket->modified == tile.modified) ||
- !(tile.debugBucket->expires == tile.expires) ||
- tile.debugBucket->debugMode != frame.debugOptions) {
- tile.debugBucket = std::make_unique<DebugBucket>(
- tile.id, tile.isRenderable(), tile.isComplete(), tile.modified,
- tile.expires, frame.debugOptions, context);
+ draw(Color::white(),
+ *tile.debugBucket->vertexBuffer,
+ *tile.debugBucket->indexBuffer,
+ tile.debugBucket->segments,
+ gl::Lines { 4.0f * frame.pixelRatio });
+
+ draw(Color::black(),
+ *tile.debugBucket->vertexBuffer,
+ *tile.debugBucket->indexBuffer,
+ tile.debugBucket->segments,
+ gl::Lines { 2.0f * frame.pixelRatio });
}
- auto& plainShader = shaders->fill;
- context.program = plainShader.getID();
- plainShader.u_matrix = matrix;
- plainShader.u_opacity = 1.0f;
-
- // Draw white outline
- plainShader.u_color = Color::white();
- context.lineWidth = 4.0f * frame.pixelRatio;
- tile.debugBucket->drawLines(plainShader, context);
-
-#if not MBGL_USE_GLES2
- // Draw line "end caps"
- MBGL_CHECK_ERROR(glPointSize(2));
- tile.debugBucket->drawPoints(plainShader, context);
-#endif // MBGL_USE_GLES2
-
- // Draw black text.
- plainShader.u_color = Color::black();
- context.lineWidth = 2.0f * frame.pixelRatio;
- tile.debugBucket->drawLines(plainShader, context);
-
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
-}
-
-void Painter::renderDebugFrame(const mat4 &matrix) {
- MBGL_DEBUG_GROUP("debug frame");
-
- // Disable depth test and don't count this towards the depth buffer,
- // but *don't* disable stencil test, as we want to clip the red tile border
- // to the tile viewport.
- context.depthTest = false;
- context.stencilOp = { gl::StencilTestOperation::Keep, gl::StencilTestOperation::Keep,
- gl::StencilTestOperation::Replace };
- context.stencilTest = true;
-
- auto& plainShader = shaders->fill;
- context.program = plainShader.getID();
- plainShader.u_matrix = matrix;
- plainShader.u_opacity = 1.0f;
-
- // draw tile outline
- tileBorderArray.bind(plainShader, tileLineStripVertexBuffer, BUFFER_OFFSET_0, context);
- plainShader.u_color = { 1.0f, 0.0f, 0.0f, 1.0f };
- context.lineWidth = 4.0f * frame.pixelRatio;
- MBGL_CHECK_ERROR(glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(tileLineStripVertexBuffer.vertexCount)));
+ if (frame.debugOptions & MapDebugOptions::TileBorders) {
+ draw(Color::red(),
+ tileVertexBuffer,
+ tileBorderIndexBuffer,
+ tileBorderSegments,
+ gl::LineStrip { 4.0f * frame.pixelRatio });
+ }
}
#ifndef NDEBUG
void Painter::renderClipMasks(PaintParameters&) {
- context.stencilTest = false;
- context.depthTest = false;
+ context.setStencilMode(gl::StencilMode::disabled());
+ context.setDepthMode(gl::DepthMode::disabled());
+ context.setColorMode(gl::ColorMode::unblended());
context.program = 0;
- context.colorMask = { true, true, true, true };
#if not MBGL_USE_GLES2
- context.pixelZoom = { 1, 1 };
- context.rasterPos = { -1, -1, 0, 0 };
+ // Reset the value in case someone else changed it, or it's dirty.
+ context.pixelTransferStencil = gl::value::PixelTransferStencil::Default;
// Read the stencil buffer
const auto viewport = context.viewport.getCurrentValue();
- auto pixels = std::make_unique<uint8_t[]>(viewport.width * viewport.height);
- MBGL_CHECK_ERROR(glReadPixels(
- viewport.x, // GLint x
- viewport.y, // GLint y
- viewport.width, // GLsizei width
- viewport.height, // GLsizei height
- GL_STENCIL_INDEX, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- pixels.get() // GLvoid * data
- ));
+ auto image =
+ context.readFramebuffer<AlphaImage, gl::TextureFormat::Stencil>(viewport.size, false);
// Scale the Stencil buffer to cover the entire color space.
- auto it = pixels.get();
- auto end = it + viewport.width * viewport.height;
+ auto it = image.data.get();
+ auto end = it + viewport.size.width * viewport.size.height;
const auto factor = 255.0f / *std::max_element(it, end);
for (; it != end; ++it) {
*it *= factor;
}
- MBGL_CHECK_ERROR(glWindowPos2i(viewport.x, viewport.y));
- MBGL_CHECK_ERROR(glDrawPixels(viewport.width, viewport.height, GL_LUMINANCE, GL_UNSIGNED_BYTE,
- pixels.get()));
+ context.pixelZoom = { 1, 1 };
+ context.rasterPos = { -1, -1, 0, 1 };
+ context.drawPixels(image);
#endif // MBGL_USE_GLES2
}
-#endif // NDEBUG
-#ifndef NDEBUG
void Painter::renderDepthBuffer(PaintParameters&) {
- context.stencilTest = false;
- context.depthTest = false;
+ context.setStencilMode(gl::StencilMode::disabled());
+ context.setDepthMode(gl::DepthMode::disabled());
+ context.setColorMode(gl::ColorMode::unblended());
context.program = 0;
- context.colorMask = { true, true, true, true };
#if not MBGL_USE_GLES2
- context.pixelZoom = { 1, 1 };
- context.rasterPos = { -1, -1, 0, 0 };
+ // Scales the values in the depth buffer so that they cover the entire grayscale range. This
+ // makes it easier to spot tiny differences.
+ const float base = 1.0f / (1.0f - depthRangeSize);
+ context.pixelTransferDepth = { base, 1.0f - base };
// Read the stencil buffer
- const auto viewport = context.viewport.getCurrentValue();
- auto pixels = std::make_unique<uint8_t[]>(viewport.width * viewport.height);
-
- const double base = 1.0 / (1.0 - depthRangeSize);
- glPixelTransferf(GL_DEPTH_SCALE, base);
- glPixelTransferf(GL_DEPTH_BIAS, 1.0 - base);
-
- MBGL_CHECK_ERROR(glReadPixels(
- viewport.x, // GLint x
- viewport.y, // GLint y
- viewport.width, // GLsizei width
- viewport.height, // GLsizei height
- GL_DEPTH_COMPONENT, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- pixels.get() // GLvoid * data
- ));
-
- MBGL_CHECK_ERROR(glWindowPos2i(viewport.x, viewport.y));
- MBGL_CHECK_ERROR(glDrawPixels(viewport.width, viewport.height, GL_LUMINANCE, GL_UNSIGNED_BYTE,
- pixels.get()));
+ auto viewport = context.viewport.getCurrentValue();
+ auto image =
+ context.readFramebuffer<AlphaImage, gl::TextureFormat::Depth>(viewport.size, false);
+
+ context.pixelZoom = { 1, 1 };
+ context.rasterPos = { -1, -1, 0, 1 };
+ context.drawPixels(image);
#endif // MBGL_USE_GLES2
}
#endif // NDEBUG
diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp
index b6606ca40b..356ccfc0b2 100644
--- a/src/mbgl/renderer/painter_fill.cpp
+++ b/src/mbgl/renderer/painter_fill.cpp
@@ -1,14 +1,12 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
-#include <mbgl/gl/gl.hpp>
-#include <mbgl/map/view.hpp>
-
#include <mbgl/renderer/fill_bucket.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
-#include <mbgl/shader/shaders.hpp>
+#include <mbgl/programs/programs.hpp>
+#include <mbgl/programs/fill_program.hpp>
#include <mbgl/util/convert.hpp>
namespace mbgl {
@@ -19,160 +17,131 @@ void Painter::renderFill(PaintParameters& parameters,
FillBucket& bucket,
const FillLayer& layer,
const RenderTile& tile) {
- const FillPaintProperties& properties = layer.impl->paint;
- mat4 vertexMatrix = tile.translatedMatrix(properties.fillTranslate,
- properties.fillTranslateAnchor,
- state);
-
- Color fillColor = properties.fillColor;
- float opacity = properties.fillOpacity;
-
- const bool isOutlineColorDefined = !properties.fillOutlineColor.isUndefined();
- Color strokeColor = isOutlineColorDefined? properties.fillOutlineColor : fillColor;
-
- const auto viewport = context.viewport.getCurrentValue();
- const std::array<GLfloat, 2> worldSize{ { static_cast<GLfloat>(viewport.width),
- static_cast<GLfloat>(viewport.height) } };
-
- bool pattern = !properties.fillPattern.value.from.empty();
- bool outline = properties.fillAntialias && !pattern && isOutlineColorDefined;
- bool fringeline = properties.fillAntialias && !pattern && !isOutlineColorDefined;
-
- context.stencilOp = { gl::StencilTestOperation::Keep, gl::StencilTestOperation::Keep,
- gl::StencilTestOperation::Replace };
- context.stencilTest = true;
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = true;
- context.lineWidth = 2.0f; // This is always fixed and does not depend on the pixelRatio!
-
- auto& outlineShader = parameters.shaders.fillOutline;
- auto& patternShader = parameters.shaders.fillPattern;
- auto& outlinePatternShader = parameters.shaders.fillOutlinePattern;
- auto& plainShader = parameters.shaders.fill;
+ const FillPaintProperties::Evaluated& properties = layer.impl->paint.evaluated;
- // Because we're drawing top-to-bottom, and we update the stencil mask
- // befrom, we have to draw the outline first (!)
- if (outline && pass == RenderPass::Translucent) {
- context.program = outlineShader.getID();
- outlineShader.u_matrix = vertexMatrix;
-
- outlineShader.u_outline_color = strokeColor;
- outlineShader.u_opacity = opacity;
-
- // Draw the entire line
- outlineShader.u_world = worldSize;
- if (isOutlineColorDefined) {
- // If we defined a different color for the fill outline, we are
- // going to ignore the bits in 0x07 and just care about the global
- // clipping mask.
- setDepthSublayer(2); // OK
- } else {
- // Otherwise, we only want to drawFill the antialiased parts that are
- // *outside* the current shape. This is important in case the fill
- // or stroke color is translucent. If we wouldn't clip to outside
- // the current shape, some pixels from the outline stroke overlapped
- // the (non-antialiased) fill.
- setDepthSublayer(0); // OK
+ if (!properties.get<FillPattern>().from.empty()) {
+ if (pass != RenderPass::Translucent) {
+ return;
}
- bucket.drawVertices(outlineShader, context, paintMode());
- }
- if (pattern) {
optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(
- properties.fillPattern.value.from, SpritePatternMode::Repeating);
- optional<SpriteAtlasPosition> imagePosB =
- spriteAtlas->getPosition(properties.fillPattern.value.to, SpritePatternMode::Repeating);
-
- // Image fill.
- if (pass == RenderPass::Translucent && imagePosA && imagePosB) {
- context.program = patternShader.getID();
- patternShader.u_matrix = vertexMatrix;
- patternShader.u_pattern_tl_a = imagePosA->tl;
- patternShader.u_pattern_br_a = imagePosA->br;
- patternShader.u_pattern_tl_b = imagePosB->tl;
- patternShader.u_pattern_br_b = imagePosB->br;
- patternShader.u_opacity = properties.fillOpacity;
- patternShader.u_image = 0;
- patternShader.u_mix = properties.fillPattern.value.t;
- patternShader.u_pattern_size_a = imagePosA->size;
- patternShader.u_pattern_size_b = imagePosB->size;
- patternShader.u_scale_a = properties.fillPattern.value.fromScale;
- patternShader.u_scale_b = properties.fillPattern.value.toScale;
- patternShader.u_tile_units_to_pixels = 1.0f / tile.id.pixelsToTileUnits(1.0f, state.getIntegerZoom());
-
- GLint tileSizeAtNearestZoom = util::tileSize * state.zoomScale(state.getIntegerZoom() - tile.id.canonical.z);
- GLint pixelX = tileSizeAtNearestZoom * (tile.id.canonical.x + tile.id.wrap * state.zoomScale(tile.id.canonical.z));
- GLint pixelY = tileSizeAtNearestZoom * tile.id.canonical.y;
- patternShader.u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
- patternShader.u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
-
- spriteAtlas->bind(true, context, 0);
+ properties.get<FillPattern>().from, SpritePatternMode::Repeating);
+ optional<SpriteAtlasPosition> imagePosB = spriteAtlas->getPosition(
+ properties.get<FillPattern>().to, SpritePatternMode::Repeating);
- // Draw the actual triangles into the color & stencil buffer.
- setDepthSublayer(0);
- bucket.drawElements(patternShader, context, paintMode());
-
- if (properties.fillAntialias && !isOutlineColorDefined) {
- context.program = outlinePatternShader.getID();
- outlinePatternShader.u_matrix = vertexMatrix;
-
- outlinePatternShader.u_pattern_tl_a = imagePosA->tl;
- outlinePatternShader.u_pattern_br_a = imagePosA->br;
- outlinePatternShader.u_pattern_tl_b = imagePosB->tl;
- outlinePatternShader.u_pattern_br_b = imagePosB->br;
- outlinePatternShader.u_opacity = properties.fillOpacity;
- outlinePatternShader.u_image = 0;
- outlinePatternShader.u_mix = properties.fillPattern.value.t;
- outlinePatternShader.u_pattern_size_a = imagePosA->size;
- outlinePatternShader.u_pattern_size_b = imagePosB->size;
- outlinePatternShader.u_scale_a = properties.fillPattern.value.fromScale;
- outlinePatternShader.u_scale_b = properties.fillPattern.value.toScale;
- outlinePatternShader.u_tile_units_to_pixels = 1.0f / tile.id.pixelsToTileUnits(1.0f, state.getIntegerZoom());
- outlinePatternShader.u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
- outlinePatternShader.u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
-
- // Draw the entire line
- outlinePatternShader.u_world = worldSize;
-
- spriteAtlas->bind(true, context, 0);
-
- setDepthSublayer(2);
- bucket.drawVertices(outlinePatternShader, context, paintMode());
- }
+ if (!imagePosA || !imagePosB) {
+ return;
}
- } else {
- // No image fill.
- if ((fillColor.a >= 1.0f && opacity >= 1.0f) == (pass == RenderPass::Opaque)) {
- // Only draw the fill when it's either opaque and we're drawing opaque
- // fragments or when it's translucent and we're drawing translucent
- // fragments
- // Draw filling rectangle.
- context.program = plainShader.getID();
- plainShader.u_matrix = vertexMatrix;
- plainShader.u_color = fillColor;
- plainShader.u_opacity = opacity;
- // Draw the actual triangles into the color & stencil buffer.
- setDepthSublayer(1);
- bucket.drawElements(plainShader, context, paintMode());
+ spriteAtlas->bind(true, context, 0);
+
+ auto draw = [&] (uint8_t sublayer,
+ auto& program,
+ const auto& drawMode,
+ const auto& vertexBuffer,
+ const auto& indexBuffer,
+ const auto& segments) {
+ program.draw(
+ context,
+ drawMode,
+ depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite),
+ stencilModeForClipping(tile.clip),
+ colorModeForRenderPass(),
+ FillPatternUniforms::values(
+ tile.translatedMatrix(properties.get<FillTranslate>(),
+ properties.get<FillTranslateAnchor>(),
+ state),
+ properties.get<FillOpacity>(),
+ context.viewport.getCurrentValue().size,
+ *imagePosA,
+ *imagePosB,
+ properties.get<FillPattern>(),
+ tile.id,
+ state
+ ),
+ vertexBuffer,
+ indexBuffer,
+ segments
+ );
+ };
+
+ draw(0,
+ parameters.programs.fillPattern,
+ gl::Triangles(),
+ *bucket.vertexBuffer,
+ *bucket.triangleIndexBuffer,
+ bucket.triangleSegments);
+
+ if (!properties.get<FillAntialias>() || !layer.impl->paint.unevaluated.get<FillOutlineColor>().isUndefined()) {
+ return;
}
- }
-
- // Because we're drawing top-to-bottom, and we update the stencil mask
- // below, we have to draw the outline first (!)
- if (fringeline && pass == RenderPass::Translucent) {
- context.program = outlineShader.getID();
- outlineShader.u_matrix = vertexMatrix;
- outlineShader.u_outline_color = fillColor;
- outlineShader.u_opacity = opacity;
+ draw(2,
+ parameters.programs.fillOutlinePattern,
+ gl::Lines { 2.0f },
+ *bucket.vertexBuffer,
+ *bucket.lineIndexBuffer,
+ bucket.lineSegments);
+ } else {
+ auto draw = [&] (uint8_t sublayer,
+ auto& program,
+ Color outlineColor,
+ const auto& drawMode,
+ const auto& vertexBuffer,
+ const auto& indexBuffer,
+ const auto& segments) {
+ program.draw(
+ context,
+ drawMode,
+ depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite),
+ stencilModeForClipping(tile.clip),
+ colorModeForRenderPass(),
+ FillProgram::UniformValues {
+ uniforms::u_matrix::Value{ tile.translatedMatrix(properties.get<FillTranslate>(),
+ properties.get<FillTranslateAnchor>(),
+ state) },
+ uniforms::u_opacity::Value{ properties.get<FillOpacity>() },
+ uniforms::u_color::Value{ properties.get<FillColor>() },
+ uniforms::u_outline_color::Value{ outlineColor },
+ uniforms::u_world::Value{ context.viewport.getCurrentValue().size },
+ },
+ vertexBuffer,
+ indexBuffer,
+ segments
+ );
+ };
+
+ if (properties.get<FillAntialias>() && !layer.impl->paint.unevaluated.get<FillOutlineColor>().isUndefined() && pass == RenderPass::Translucent) {
+ draw(2,
+ parameters.programs.fillOutline,
+ properties.get<FillOutlineColor>(),
+ gl::Lines { 2.0f },
+ *bucket.vertexBuffer,
+ *bucket.lineIndexBuffer,
+ bucket.lineSegments);
+ }
- // Draw the entire line
- outlineShader.u_world = worldSize;
+ // Only draw the fill when it's opaque and we're drawing opaque fragments,
+ // or when it's translucent and we're drawing translucent fragments.
+ if ((properties.get<FillColor>().a >= 1.0f && properties.get<FillOpacity>() >= 1.0f) == (pass == RenderPass::Opaque)) {
+ draw(1,
+ parameters.programs.fill,
+ properties.get<FillOutlineColor>(),
+ gl::Triangles(),
+ *bucket.vertexBuffer,
+ *bucket.triangleIndexBuffer,
+ bucket.triangleSegments);
+ }
- setDepthSublayer(2);
- bucket.drawVertices(outlineShader, context, paintMode());
+ if (properties.get<FillAntialias>() && layer.impl->paint.unevaluated.get<FillOutlineColor>().isUndefined() && pass == RenderPass::Translucent) {
+ draw(2,
+ parameters.programs.fillOutline,
+ properties.get<FillColor>(),
+ gl::Lines { 2.0f },
+ *bucket.vertexBuffer,
+ *bucket.lineIndexBuffer,
+ bucket.lineSegments);
+ }
}
}
diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp
index 85a5786353..012746d2f2 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -4,10 +4,10 @@
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
-#include <mbgl/shader/shaders.hpp>
+#include <mbgl/programs/programs.hpp>
+#include <mbgl/programs/line_program.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/geometry/line_atlas.hpp>
-#include <mbgl/util/mat2.hpp>
namespace mbgl {
@@ -17,150 +17,73 @@ void Painter::renderLine(PaintParameters& parameters,
LineBucket& bucket,
const LineLayer& layer,
const RenderTile& tile) {
- // Abort early.
- if (pass == RenderPass::Opaque) return;
-
- context.stencilOp = { gl::StencilTestOperation::Keep, gl::StencilTestOperation::Keep,
- gl::StencilTestOperation::Replace };
- context.stencilTest = true;
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = false;
-
- const auto& properties = layer.impl->paint;
- const auto& layout = bucket.layout;
-
- // the distance over which the line edge fades out.
- // Retina devices need a smaller distance to avoid aliasing.
- float antialiasing = 1.0 / frame.pixelRatio;
-
- float blur = properties.lineBlur + antialiasing;
-
- const Color color = properties.lineColor;
- const float opacity = properties.lineOpacity;
- const float ratio = 1.0 / tile.id.pixelsToTileUnits(1.0, state.getZoom());
-
- mat2 antialiasingMatrix;
- matrix::identity(antialiasingMatrix);
- matrix::scale(antialiasingMatrix, antialiasingMatrix, 1.0, std::cos(state.getPitch()));
- matrix::rotate(antialiasingMatrix, antialiasingMatrix, state.getAngle());
-
- // calculate how much longer the real world distance is at the top of the screen
- // than at the middle of the screen.
- float topedgelength = std::sqrt(std::pow(state.getHeight(), 2.0f) / 4.0f * (1.0f + std::pow(state.getAltitude(), 2.0f)));
- float x = state.getHeight() / 2.0f * std::tan(state.getPitch());
- float extra = (topedgelength + x) / topedgelength - 1.0f;
-
- mat4 vtxMatrix = tile.translatedMatrix(properties.lineTranslate,
- properties.lineTranslateAnchor,
- state);
-
- setDepthSublayer(0);
-
- auto& linesdfShader = parameters.shaders.lineSDF;
- auto& linepatternShader = parameters.shaders.linePattern;
- auto& lineShader = parameters.shaders.line;
-
- if (!properties.lineDasharray.value.from.empty()) {
- context.program = linesdfShader.getID();
-
- linesdfShader.u_matrix = vtxMatrix;
- linesdfShader.u_linewidth = properties.lineWidth / 2;
- linesdfShader.u_gapwidth = properties.lineGapWidth / 2;
- linesdfShader.u_antialiasing = antialiasing / 2;
- linesdfShader.u_ratio = ratio;
- linesdfShader.u_blur = blur;
- linesdfShader.u_color = color;
- linesdfShader.u_opacity = opacity;
-
- const LinePatternCap cap =
- layout.lineCap == LineCapType::Round ? LinePatternCap::Round : LinePatternCap::Square;
- LinePatternPos posA = lineAtlas->getDashPosition(properties.lineDasharray.value.from, cap);
- LinePatternPos posB = lineAtlas->getDashPosition(properties.lineDasharray.value.to, cap);
-
- const float widthA = posA.width * properties.lineDasharray.value.fromScale * layer.impl->dashLineWidth;
- const float widthB = posB.width * properties.lineDasharray.value.toScale * layer.impl->dashLineWidth;
-
- float scaleXA = 1.0 / tile.id.pixelsToTileUnits(widthA, state.getIntegerZoom());
- float scaleYA = -posA.height / 2.0;
- float scaleXB = 1.0 / tile.id.pixelsToTileUnits(widthB, state.getIntegerZoom());
- float scaleYB = -posB.height / 2.0;
+ if (pass == RenderPass::Opaque) {
+ return;
+ }
- linesdfShader.u_patternscale_a = {{ scaleXA, scaleYA }};
- linesdfShader.u_tex_y_a = posA.y;
- linesdfShader.u_patternscale_b = {{ scaleXB, scaleYB }};
- linesdfShader.u_tex_y_b = posB.y;
- linesdfShader.u_sdfgamma = lineAtlas->width / (std::min(widthA, widthB) * 256.0 * frame.pixelRatio) / 2;
- linesdfShader.u_mix = properties.lineDasharray.value.t;
- linesdfShader.u_extra = extra;
- linesdfShader.u_offset = -properties.lineOffset;
- linesdfShader.u_antialiasingmatrix = antialiasingMatrix;
+ const LinePaintProperties::Evaluated& properties = layer.impl->paint.evaluated;
+
+ auto draw = [&] (auto& program, auto&& uniformValues) {
+ program.draw(
+ context,
+ gl::Triangles(),
+ depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ stencilModeForClipping(tile.clip),
+ colorModeForRenderPass(),
+ std::move(uniformValues),
+ *bucket.vertexBuffer,
+ *bucket.indexBuffer,
+ bucket.segments
+ );
+ };
+
+ if (!properties.get<LineDasharray>().from.empty()) {
+ const LinePatternCap cap = bucket.layout.get<LineCap>() == LineCapType::Round
+ ? LinePatternCap::Round : LinePatternCap::Square;
+ LinePatternPos posA = lineAtlas->getDashPosition(properties.get<LineDasharray>().from, cap);
+ LinePatternPos posB = lineAtlas->getDashPosition(properties.get<LineDasharray>().to, cap);
- linesdfShader.u_image = 0;
lineAtlas->bind(context, 0);
- bucket.drawLineSDF(linesdfShader, context, paintMode());
-
- } else if (!properties.linePattern.value.from.empty()) {
- optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(
- properties.linePattern.value.from, SpritePatternMode::Repeating);
- optional<SpriteAtlasPosition> imagePosB =
- spriteAtlas->getPosition(properties.linePattern.value.to, SpritePatternMode::Repeating);
-
- if (!imagePosA || !imagePosB)
+ draw(parameters.programs.lineSDF,
+ LineSDFProgram::uniformValues(
+ properties,
+ frame.pixelRatio,
+ tile,
+ state,
+ pixelsToGLUnits,
+ posA,
+ posB,
+ layer.impl->dashLineWidth,
+ lineAtlas->getSize().width));
+
+ } else if (!properties.get<LinePattern>().from.empty()) {
+ optional<SpriteAtlasPosition> posA = spriteAtlas->getPosition(
+ properties.get<LinePattern>().from, SpritePatternMode::Repeating);
+ optional<SpriteAtlasPosition> posB = spriteAtlas->getPosition(
+ properties.get<LinePattern>().to, SpritePatternMode::Repeating);
+
+ if (!posA || !posB)
return;
- context.program = linepatternShader.getID();
-
- linepatternShader.u_matrix = vtxMatrix;
- linepatternShader.u_linewidth = properties.lineWidth / 2;
- linepatternShader.u_gapwidth = properties.lineGapWidth / 2;
- linepatternShader.u_antialiasing = antialiasing / 2;
- linepatternShader.u_ratio = ratio;
- linepatternShader.u_blur = blur;
-
- linepatternShader.u_pattern_size_a = {{
- tile.id.pixelsToTileUnits((*imagePosA).size[0] * properties.linePattern.value.fromScale, state.getIntegerZoom()),
- (*imagePosA).size[1]
- }};
- linepatternShader.u_pattern_tl_a = (*imagePosA).tl;
- linepatternShader.u_pattern_br_a = (*imagePosA).br;
-
- linepatternShader.u_pattern_size_b = {{
- tile.id.pixelsToTileUnits((*imagePosB).size[0] * properties.linePattern.value.toScale, state.getIntegerZoom()),
- (*imagePosB).size[1]
- }};
- linepatternShader.u_pattern_tl_b = (*imagePosB).tl;
- linepatternShader.u_pattern_br_b = (*imagePosB).br;
-
- linepatternShader.u_fade = properties.linePattern.value.t;
- linepatternShader.u_opacity = properties.lineOpacity;
- linepatternShader.u_extra = extra;
- linepatternShader.u_offset = -properties.lineOffset;
- linepatternShader.u_antialiasingmatrix = antialiasingMatrix;
-
- linepatternShader.u_image = 0;
spriteAtlas->bind(true, context, 0);
- bucket.drawLinePatterns(linepatternShader, context, paintMode());
+ draw(parameters.programs.linePattern,
+ LinePatternProgram::uniformValues(
+ properties,
+ tile,
+ state,
+ pixelsToGLUnits,
+ *posA,
+ *posB));
} else {
- context.program = lineShader.getID();
-
- lineShader.u_matrix = vtxMatrix;
- lineShader.u_linewidth = properties.lineWidth / 2;
- lineShader.u_gapwidth = properties.lineGapWidth / 2;
- lineShader.u_antialiasing = antialiasing / 2;
- lineShader.u_ratio = ratio;
- lineShader.u_blur = blur;
- lineShader.u_extra = extra;
- lineShader.u_offset = -properties.lineOffset;
- lineShader.u_antialiasingmatrix = antialiasingMatrix;
-
- lineShader.u_color = color;
- lineShader.u_opacity = opacity;
-
- bucket.drawLines(lineShader, context, paintMode());
+ draw(parameters.programs.line,
+ LineProgram::uniformValues(
+ properties,
+ tile,
+ state,
+ pixelsToGLUnits));
}
}
diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp
index 8b39c8adf8..dcf2644140 100644
--- a/src/mbgl/renderer/painter_raster.cpp
+++ b/src/mbgl/renderer/painter_raster.cpp
@@ -1,57 +1,17 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_tile.hpp>
-#include <mbgl/gl/gl.hpp>
#include <mbgl/renderer/raster_bucket.hpp>
#include <mbgl/style/layers/raster_layer.hpp>
#include <mbgl/style/layers/raster_layer_impl.hpp>
-#include <mbgl/shader/shaders.hpp>
+#include <mbgl/programs/programs.hpp>
+#include <mbgl/programs/raster_program.hpp>
namespace mbgl {
using namespace style;
-void Painter::renderRaster(PaintParameters& parameters,
- RasterBucket& bucket,
- const RasterLayer& layer,
- const RenderTile& tile) {
- if (pass != RenderPass::Translucent) return;
-
- const RasterPaintProperties& properties = layer.impl->paint;
-
- if (bucket.hasData()) {
- auto& rasterShader = parameters.shaders.raster;
- auto& rasterVAO = parameters.shaders.coveringRasterArray;
-
- context.program = rasterShader.getID();
- rasterShader.u_matrix = tile.matrix;
- rasterShader.u_buffer_scale = 1.0f;
- rasterShader.u_opacity0 = properties.rasterOpacity;
- rasterShader.u_opacity1 = 0;
-
- rasterShader.u_brightness_low = properties.rasterBrightnessMin;
- rasterShader.u_brightness_high = properties.rasterBrightnessMax;
- rasterShader.u_saturation_factor = saturationFactor(properties.rasterSaturation);
- rasterShader.u_contrast_factor = contrastFactor(properties.rasterContrast);
- rasterShader.u_spin_weights = spinWeights(properties.rasterHueRotate);
-
- context.stencilTest = false;
-
- rasterShader.u_image0 = 0; // GL_TEXTURE0
- rasterShader.u_image1 = 1; // GL_TEXTURE1
- rasterShader.u_tl_parent = {{ 0.0f, 0.0f }};
- rasterShader.u_scale_parent = 1.0f;
-
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- context.depthMask = false;
- setDepthSublayer(0);
-
- bucket.drawRaster(rasterShader, rasterVertexBuffer, rasterVAO, context);
- }
-}
-
-float Painter::saturationFactor(float saturation) {
+static float saturationFactor(float saturation) {
if (saturation > 0) {
return 1 - 1 / (1.001 - saturation);
} else {
@@ -59,7 +19,7 @@ float Painter::saturationFactor(float saturation) {
}
}
-float Painter::contrastFactor(float contrast) {
+static float contrastFactor(float contrast) {
if (contrast > 0) {
return 1 / (1 - contrast);
} else {
@@ -67,7 +27,7 @@ float Painter::contrastFactor(float contrast) {
}
}
-std::array<float, 3> Painter::spinWeights(float spin) {
+static std::array<float, 3> spinWeights(float spin) {
spin *= util::DEG2RAD;
float s = std::sin(spin);
float c = std::cos(spin);
@@ -79,4 +39,46 @@ std::array<float, 3> Painter::spinWeights(float spin) {
return spin_weights;
}
+void Painter::renderRaster(PaintParameters& parameters,
+ RasterBucket& bucket,
+ const RasterLayer& layer,
+ const RenderTile& tile) {
+ if (pass != RenderPass::Translucent)
+ return;
+ if (!bucket.hasData())
+ return;
+
+ const RasterPaintProperties::Evaluated& properties = layer.impl->paint.evaluated;
+
+ assert(bucket.texture);
+ context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear);
+ context.bindTexture(*bucket.texture, 1, gl::TextureFilter::Linear);
+
+ parameters.programs.raster.draw(
+ context,
+ gl::Triangles(),
+ depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ RasterProgram::UniformValues {
+ uniforms::u_matrix::Value{ tile.matrix },
+ uniforms::u_image0::Value{ 0 },
+ uniforms::u_image1::Value{ 1 },
+ uniforms::u_opacity::Value{ properties.get<RasterOpacity>() },
+ uniforms::u_fade_t::Value{ 1 },
+ uniforms::u_brightness_low::Value{ properties.get<RasterBrightnessMin>() },
+ uniforms::u_brightness_high::Value{ properties.get<RasterBrightnessMax>() },
+ uniforms::u_saturation_factor::Value{ saturationFactor(properties.get<RasterSaturation>()) },
+ uniforms::u_contrast_factor::Value{ contrastFactor(properties.get<RasterContrast>()) },
+ uniforms::u_spin_weights::Value{ spinWeights(properties.get<RasterHueRotate>()) },
+ uniforms::u_buffer_scale::Value{ 1.0f },
+ uniforms::u_scale_parent::Value{ 1.0f },
+ uniforms::u_tl_parent::Value{ std::array<float, 2> {{ 0.0f, 0.0f }} },
+ },
+ rasterVertexBuffer,
+ tileTriangleIndexBuffer,
+ rasterSegments
+ );
+}
+
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp
index 2ed6facad8..39075976a0 100644
--- a/src/mbgl/renderer/painter_symbol.cpp
+++ b/src/mbgl/renderer/painter_symbol.cpp
@@ -6,8 +6,11 @@
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
-#include <mbgl/shader/shaders.hpp>
+#include <mbgl/programs/programs.hpp>
+#include <mbgl/programs/symbol_program.hpp>
+#include <mbgl/programs/collision_box_program.hpp>
#include <mbgl/util/math.hpp>
+#include <mbgl/tile/tile.hpp>
#include <cmath>
@@ -15,254 +18,114 @@ namespace mbgl {
using namespace style;
-void Painter::renderSDF(SymbolBucket& bucket,
- const RenderTile& tile,
- float sdfFontSize,
- std::array<float, 2> texsize,
- SymbolSDFShader& sdfShader,
- void (SymbolBucket::*drawSDF)(SymbolSDFShader&, gl::Context&, PaintMode),
-
- // Layout
- AlignmentType rotationAlignment,
- AlignmentType pitchAlignment,
- float layoutSize,
-
- // Paint
- float opacity,
- Color color,
- Color haloColor,
- float haloWidth,
- float haloBlur,
- std::array<float, 2> translate,
- TranslateAnchorType translateAnchor,
- float paintSize)
-{
- mat4 vtxMatrix = tile.translatedMatrix(translate, translateAnchor, state);
-
- // If layerStyle.size > bucket.info.fontSize then labels may collide
- float fontSize = paintSize;
- float fontScale = fontSize / sdfFontSize;
-
- bool rotateWithMap = rotationAlignment == AlignmentType::Map;
- bool pitchWithMap = pitchAlignment == AlignmentType::Map;
-
- std::array<float, 2> extrudeScale;
- float gammaScale;
-
- if (pitchWithMap) {
- gammaScale = 1.0 / std::cos(state.getPitch());
- extrudeScale.fill(tile.id.pixelsToTileUnits(1, state.getZoom()) * fontScale);
- } else {
- gammaScale = 1.0;
- extrudeScale = {{
- pixelsToGLUnits[0] * fontScale * state.getAltitude(),
- pixelsToGLUnits[1] * fontScale * state.getAltitude()
- }};
- }
-
- context.program = sdfShader.getID();
- sdfShader.u_matrix = vtxMatrix;
- sdfShader.u_extrude_scale = extrudeScale;
- sdfShader.u_texsize = texsize;
- sdfShader.u_rotate_with_map = rotateWithMap;
- sdfShader.u_pitch_with_map = pitchWithMap;
- sdfShader.u_texture = 0;
- sdfShader.u_pitch = state.getPitch();
- sdfShader.u_bearing = -1.0f * state.getAngle();
- sdfShader.u_aspect_ratio = (state.getWidth() * 1.0f) / (state.getHeight() * 1.0f);
-
- // adjust min/max zooms for variable font sies
- float zoomAdjust = std::log(fontSize / layoutSize) / std::log(2);
-
- sdfShader.u_zoom = (state.getZoom() - zoomAdjust) * 10; // current zoom level
-
- frameHistory.bind(context, 1);
- sdfShader.u_fadetexture = 1;
-
- // The default gamma value has to be adjust for the current pixelratio so that we're not
- // drawing blurry font on retina screens.
- const float gamma = 0.105 * sdfFontSize / fontSize / frame.pixelRatio;
-
- const float sdfPx = 8.0f;
- const float blurOffset = 1.19f;
- const float haloOffset = 6.0f;
-
- // We're drawing in the translucent pass which is bottom-to-top, so we need
- // to draw the halo first.
- if (haloColor.a > 0.0f && haloWidth > 0.0f) {
- sdfShader.u_gamma = (haloBlur * blurOffset / fontScale / sdfPx + gamma) * gammaScale;
- sdfShader.u_color = haloColor;
- sdfShader.u_opacity = opacity;
- sdfShader.u_buffer = (haloOffset - haloWidth / fontScale) / sdfPx;
- (bucket.*drawSDF)(sdfShader, context, paintMode());
- }
-
- // Then, we draw the text/icon over the halo
- if (color.a > 0.0f) {
- sdfShader.u_gamma = gamma * gammaScale;
- sdfShader.u_color = color;
- sdfShader.u_opacity = opacity;
- sdfShader.u_buffer = (256.0f - 64.0f) / 256.0f;
- (bucket.*drawSDF)(sdfShader, context, paintMode());
- }
-}
-
void Painter::renderSymbol(PaintParameters& parameters,
SymbolBucket& bucket,
const SymbolLayer& layer,
const RenderTile& tile) {
- // Abort early.
if (pass == RenderPass::Opaque) {
return;
}
- const auto& paint = layer.impl->paint;
const auto& layout = bucket.layout;
- context.depthMask = false;
-
- // TODO remove the `true ||` when #1673 is implemented
- const bool drawAcrossEdges = (frame.mapMode == MapMode::Continuous) && (true || !(layout.textAllowOverlap || layout.iconAllowOverlap ||
- layout.textIgnorePlacement || layout.iconIgnorePlacement));
-
- // Disable the stencil test so that labels aren't clipped to tile boundaries.
- //
- // Layers with features that may be drawn overlapping aren't clipped. These
- // layers are sorted in the y direction, and to draw the correct ordering near
- // tile edges the icons are included in both tiles and clipped when drawing.
- if (drawAcrossEdges) {
- context.stencilTest = false;
- } else {
- context.stencilOp = { gl::StencilTestOperation::Keep, gl::StencilTestOperation::Keep,
- gl::StencilTestOperation::Replace };
- context.stencilTest = true;
- }
+ frameHistory.bind(context, 1);
- setDepthSublayer(0);
+ auto draw = [&] (auto& program,
+ auto&& uniformValues,
+ const auto& buffers,
+ const SymbolPropertyValues& values_)
+ {
+ // We clip symbols to their tile extent in still mode.
+ const bool needsClipping = frame.mapMode == MapMode::Still;
+
+ program.draw(
+ context,
+ gl::Triangles(),
+ values_.pitchAlignment == AlignmentType::Map
+ ? depthModeForSublayer(0, gl::DepthMode::ReadOnly)
+ : gl::DepthMode::disabled(),
+ needsClipping
+ ? stencilModeForClipping(tile.clip)
+ : gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ std::move(uniformValues),
+ *buffers.vertexBuffer,
+ *buffers.indexBuffer,
+ buffers.segments
+ );
+ };
if (bucket.hasIconData()) {
- if (layout.iconRotationAlignment == AlignmentType::Map) {
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- } else {
- context.depthTest = false;
- }
+ auto values = layer.impl->iconPropertyValues(layout);
- bool sdf = bucket.sdfIcons;
+ SpriteAtlas& atlas = *layer.impl->spriteAtlas;
+ const bool iconScaled = values.paintSize != 1.0f || frame.pixelRatio != atlas.getPixelRatio() || bucket.iconsNeedLinear;
+ const bool iconTransformed = values.rotationAlignment == AlignmentType::Map || state.getPitch() != 0;
+ atlas.bind(bucket.sdfIcons || state.isChanging() || iconScaled || iconTransformed, context, 0);
- const float angleOffset =
- layout.iconRotationAlignment == AlignmentType::Map
- ? state.getAngle()
- : 0;
+ const Size texsize = atlas.getSize();
- const float fontSize = layer.impl->iconSize;
- const float fontScale = fontSize / 1.0f;
-
- SpriteAtlas* activeSpriteAtlas = layer.impl->spriteAtlas;
- const bool iconScaled = fontScale != 1 || frame.pixelRatio != activeSpriteAtlas->getPixelRatio() || bucket.iconsNeedLinear;
- const bool iconTransformed = layout.iconRotationAlignment == AlignmentType::Map || angleOffset != 0 || state.getPitch() != 0;
- activeSpriteAtlas->bind(sdf || state.isChanging() || iconScaled || iconTransformed, context, 0);
-
- if (sdf) {
- renderSDF(bucket,
- tile,
- 1.0f,
- {{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }},
- parameters.shaders.symbolIconSDF,
- &SymbolBucket::drawIcons,
- layout.iconRotationAlignment,
- // icon-pitch-alignment is not yet implemented
- // and we simply inherit the rotation alignment
- layout.iconRotationAlignment,
- layout.iconSize,
- paint.iconOpacity,
- paint.iconColor,
- paint.iconHaloColor,
- paint.iconHaloWidth,
- paint.iconHaloBlur,
- paint.iconTranslate,
- paint.iconTranslateAnchor,
- layer.impl->iconSize);
- } else {
- mat4 vtxMatrix = tile.translatedMatrix(paint.iconTranslate,
- paint.iconTranslateAnchor,
- state);
-
- std::array<float, 2> extrudeScale;
-
- const bool alignedWithMap = layout.iconRotationAlignment == AlignmentType::Map;
- if (alignedWithMap) {
- extrudeScale.fill(tile.id.pixelsToTileUnits(1, state.getZoom()) * fontScale);
- } else {
- extrudeScale = {{
- pixelsToGLUnits[0] * fontScale * state.getAltitude(),
- pixelsToGLUnits[1] * fontScale * state.getAltitude()
- }};
+ if (bucket.sdfIcons) {
+ if (values.hasHalo()) {
+ draw(parameters.programs.symbolIconSDF,
+ SymbolSDFProgram::haloUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ bucket.icon,
+ values);
}
- auto& iconShader = parameters.shaders.symbolIcon;
+ if (values.hasForeground()) {
+ draw(parameters.programs.symbolIconSDF,
+ SymbolSDFProgram::foregroundUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ bucket.icon,
+ values);
+ }
+ } else {
+ draw(parameters.programs.symbolIcon,
+ SymbolIconProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state),
+ bucket.icon,
+ values);
+ }
+ }
- context.program = iconShader.getID();
- iconShader.u_matrix = vtxMatrix;
- iconShader.u_extrude_scale = extrudeScale;
- iconShader.u_texsize = {{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }};
- iconShader.u_rotate_with_map = alignedWithMap;
- iconShader.u_texture = 0;
+ if (bucket.hasTextData()) {
+ glyphAtlas->bind(context, 0);
- // adjust min/max zooms for variable font sies
- float zoomAdjust = std::log(fontSize / layout.iconSize) / std::log(2);
- iconShader.u_zoom = (state.getZoom() - zoomAdjust) * 10; // current zoom level
- iconShader.u_opacity = paint.iconOpacity;
+ auto values = layer.impl->textPropertyValues(layout);
- frameHistory.bind(context, 1);
- iconShader.u_fadetexture = 1;
+ const Size texsize = glyphAtlas->getSize();
- bucket.drawIcons(iconShader, context, paintMode());
+ if (values.hasHalo()) {
+ draw(parameters.programs.symbolGlyph,
+ SymbolSDFProgram::haloUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ bucket.text,
+ values);
}
- }
- if (bucket.hasTextData()) {
- if (layout.textPitchAlignment == AlignmentType::Map) {
- context.depthFunc = gl::DepthTestFunction::LessEqual;
- context.depthTest = true;
- } else {
- context.depthTest = false;
+ if (values.hasForeground()) {
+ draw(parameters.programs.symbolGlyph,
+ SymbolSDFProgram::foregroundUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ bucket.text,
+ values);
}
-
- glyphAtlas->bind(context, 0);
-
- renderSDF(bucket,
- tile,
- 24.0f,
- {{ float(glyphAtlas->width) / 4, float(glyphAtlas->height) / 4 }},
- parameters.shaders.symbolGlyph,
- &SymbolBucket::drawGlyphs,
- layout.textRotationAlignment,
- layout.textPitchAlignment,
- layout.textSize,
- paint.textOpacity,
- paint.textColor,
- paint.textHaloColor,
- paint.textHaloWidth,
- paint.textHaloBlur,
- paint.textTranslate,
- paint.textTranslateAnchor,
- layer.impl->textSize);
}
if (bucket.hasCollisionBoxData()) {
- context.stencilTest = false;
-
- auto& collisionBoxShader = shaders->collisionBox;
- context.program = collisionBoxShader.getID();
- collisionBoxShader.u_matrix = tile.matrix;
- // TODO: This was the overscaled z instead of the canonical z.
- collisionBoxShader.u_scale = std::pow(2, state.getZoom() - tile.id.canonical.z);
- collisionBoxShader.u_zoom = state.getZoom() * 10;
- collisionBoxShader.u_maxzoom = (tile.id.canonical.z + 1) * 10;
- context.lineWidth = 1.0f;
-
- bucket.drawCollisionBoxes(collisionBoxShader, context);
+ programs->collisionBox.draw(
+ context,
+ gl::Lines { 1.0f },
+ gl::DepthMode::disabled(),
+ gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ CollisionBoxProgram::UniformValues {
+ uniforms::u_matrix::Value{ tile.matrix },
+ uniforms::u_scale::Value{ std::pow(2.0f, float(state.getZoom() - tile.tile.id.overscaledZ)) },
+ uniforms::u_zoom::Value{ float(state.getZoom() * 10) },
+ uniforms::u_maxzoom::Value{ float((tile.id.canonical.z + 1) * 10) },
+ },
+ *bucket.collisionBox.vertexBuffer,
+ *bucket.collisionBox.indexBuffer,
+ bucket.collisionBox.segments
+ );
}
}
diff --git a/src/mbgl/renderer/raster_bucket.cpp b/src/mbgl/renderer/raster_bucket.cpp
index 80d6dfe8dd..f328ad9313 100644
--- a/src/mbgl/renderer/raster_bucket.cpp
+++ b/src/mbgl/renderer/raster_bucket.cpp
@@ -1,20 +1,18 @@
#include <mbgl/renderer/raster_bucket.hpp>
#include <mbgl/style/layers/raster_layer.hpp>
-#include <mbgl/shader/raster_shader.hpp>
+#include <mbgl/programs/raster_program.hpp>
#include <mbgl/renderer/painter.hpp>
-#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/context.hpp>
namespace mbgl {
using namespace style;
-RasterBucket::RasterBucket(PremultipliedImage&& image_) : image(std::move(image_)) {
+RasterBucket::RasterBucket(UnassociatedImage&& image_) : image(std::move(image_)) {
}
void RasterBucket::upload(gl::Context& context) {
- texture = context.createTexture(image);
- image = {};
+ texture = context.createTexture(std::move(image));
uploaded = true;
}
@@ -25,23 +23,8 @@ void RasterBucket::render(Painter& painter,
painter.renderRaster(parameters, *this, *layer.as<RasterLayer>(), tile);
}
-void RasterBucket::drawRaster(RasterShader& shader,
- gl::VertexBuffer<RasterVertex>& vertices,
- gl::VertexArrayObject& array,
- gl::Context& context) {
- assert(texture);
- context.bindTexture(*texture, 0, gl::TextureFilter::Linear);
- context.bindTexture(*texture, 1, gl::TextureFilter::Linear);
- array.bind(shader, vertices, BUFFER_OFFSET_0, context);
- MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, static_cast<GLsizei>(vertices.vertexCount)));
-}
-
bool RasterBucket::hasData() const {
return true;
}
-bool RasterBucket::needsClipping() const {
- return false;
-}
-
} // namespace mbgl
diff --git a/src/mbgl/renderer/raster_bucket.hpp b/src/mbgl/renderer/raster_bucket.hpp
index b0d3ca49c7..20969cf6b8 100644
--- a/src/mbgl/renderer/raster_bucket.hpp
+++ b/src/mbgl/renderer/raster_bucket.hpp
@@ -7,28 +7,15 @@
namespace mbgl {
-class RasterShader;
-class RasterVertex;
-
-namespace gl {
-class Context;
-template <class> class VertexBuffer;
-class VertexArrayObject;
-} // namespace gl
-
class RasterBucket : public Bucket {
public:
- RasterBucket(PremultipliedImage&&);
+ RasterBucket(UnassociatedImage&&);
void upload(gl::Context&) override;
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;
bool hasData() const override;
- bool needsClipping() const override;
-
- void drawRaster(RasterShader&, gl::VertexBuffer<RasterVertex>&, gl::VertexArrayObject&, gl::Context&);
-private:
- PremultipliedImage image;
+ UnassociatedImage image;
optional<gl::Texture> texture;
};
diff --git a/src/mbgl/renderer/render_tile.hpp b/src/mbgl/renderer/render_tile.hpp
index 74669faaf9..e2e0c3d656 100644
--- a/src/mbgl/renderer/render_tile.hpp
+++ b/src/mbgl/renderer/render_tile.hpp
@@ -24,6 +24,7 @@ public:
Tile& tile;
ClipID clip;
mat4 matrix;
+ bool used = false;
mat4 translatedMatrix(const std::array<float, 2>& translate,
style::TranslateAnchorType anchor,
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp
index 565c58c7ed..0f2c89339f 100644
--- a/src/mbgl/renderer/symbol_bucket.cpp
+++ b/src/mbgl/renderer/symbol_bucket.cpp
@@ -1,17 +1,13 @@
#include <mbgl/renderer/symbol_bucket.hpp>
#include <mbgl/renderer/painter.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
-#include <mbgl/shader/symbol_sdf_shader.hpp>
-#include <mbgl/shader/symbol_icon_shader.hpp>
-#include <mbgl/shader/collision_box_shader.hpp>
-#include <mbgl/gl/gl.hpp>
namespace mbgl {
using namespace style;
SymbolBucket::SymbolBucket(const MapMode mode_,
- style::SymbolLayoutProperties layout_,
+ style::SymbolLayoutProperties::Evaluated layout_,
bool sdfIcons_,
bool iconsNeedLinear_)
: mode(mode_),
@@ -31,8 +27,9 @@ void SymbolBucket::upload(gl::Context& context) {
icon.indexBuffer = context.createIndexBuffer(std::move(icon.triangles));
}
- if (hasCollisionBoxData()) {
+ if (!collisionBox.vertices.empty()) {
collisionBox.vertexBuffer = context.createVertexBuffer(std::move(collisionBox.vertices));
+ collisionBox.indexBuffer = context.createIndexBuffer(std::move(collisionBox.lines));
}
uploaded = true;
@@ -46,79 +43,20 @@ void SymbolBucket::render(Painter& painter,
}
bool SymbolBucket::hasData() const {
- assert(false); // Should be calling SymbolLayout::hasSymbolInstances() instead.
+ assert(false); // Should be calling SymbolLayout::has{Text,Icon,CollisonBox}Data() instead.
return false;
}
bool SymbolBucket::hasTextData() const {
- return !text.groups.empty();
+ return !text.segments.empty();
}
bool SymbolBucket::hasIconData() const {
- return !icon.groups.empty();
+ return !icon.segments.empty();
}
bool SymbolBucket::hasCollisionBoxData() const {
- return !collisionBox.groups.empty();
-}
-
-bool SymbolBucket::needsClipping() const {
- return mode == MapMode::Still;
-}
-
-void SymbolBucket::drawGlyphs(SymbolSDFShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET_0;
- GLbyte* elements_index = BUFFER_OFFSET_0;
- for (auto& group : text.groups) {
- group.getVAO(shader, paintMode).bind(
- shader, *text.vertexBuffer, *text.indexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * text.vertexBuffer->vertexSize;
- elements_index += group.indexLength * text.indexBuffer->primitiveSize;
- }
-}
-
-void SymbolBucket::drawIcons(SymbolSDFShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET_0;
- GLbyte* elements_index = BUFFER_OFFSET_0;
- for (auto& group : icon.groups) {
- group.getVAO(shader, paintMode).bind(
- shader, *icon.vertexBuffer, *icon.indexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * icon.vertexBuffer->vertexSize;
- elements_index += group.indexLength * icon.indexBuffer->primitiveSize;
- }
-}
-
-void SymbolBucket::drawIcons(SymbolIconShader& shader,
- gl::Context& context,
- PaintMode paintMode) {
- GLbyte* vertex_index = BUFFER_OFFSET_0;
- GLbyte* elements_index = BUFFER_OFFSET_0;
- for (auto& group : icon.groups) {
- group.getVAO(shader, paintMode).bind(
- shader, *icon.vertexBuffer, *icon.indexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(group.indexLength * 3), GL_UNSIGNED_SHORT,
- elements_index));
- vertex_index += group.vertexLength * icon.vertexBuffer->vertexSize;
- elements_index += group.indexLength * icon.indexBuffer->primitiveSize;
- }
-}
-
-void SymbolBucket::drawCollisionBoxes(CollisionBoxShader& shader,
- gl::Context& context) {
- GLbyte* vertex_index = BUFFER_OFFSET_0;
- for (auto& group : collisionBox.groups) {
- group.getVAO(shader, PaintMode::Regular).bind(
- shader, *collisionBox.vertexBuffer, vertex_index, context);
- MBGL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(group.vertexLength)));
- }
+ return !collisionBox.segments.empty();
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp
index e5180c31e2..d62a61aab7 100644
--- a/src/mbgl/renderer/symbol_bucket.hpp
+++ b/src/mbgl/renderer/symbol_bucket.hpp
@@ -1,28 +1,23 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/renderer/element_group.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/gl/index_buffer.hpp>
-#include <mbgl/shader/symbol_vertex.hpp>
-#include <mbgl/shader/collision_box_vertex.hpp>
+#include <mbgl/gl/segment.hpp>
+#include <mbgl/programs/symbol_program.hpp>
+#include <mbgl/programs/collision_box_program.hpp>
#include <mbgl/text/glyph_range.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
-#include <memory>
#include <vector>
namespace mbgl {
-class SymbolSDFShader;
-class SymbolIconShader;
-class CollisionBoxShader;
-
class SymbolBucket : public Bucket {
public:
SymbolBucket(const MapMode,
- style::SymbolLayoutProperties,
+ style::SymbolLayoutProperties::Evaluated,
bool sdfIcons,
bool iconsNeedLinear);
@@ -32,46 +27,37 @@ public:
bool hasTextData() const;
bool hasIconData() const;
bool hasCollisionBoxData() const;
- bool needsClipping() const override;
-
- void drawGlyphs(SymbolSDFShader&, gl::Context&, PaintMode);
- void drawIcons(SymbolSDFShader&, gl::Context&, PaintMode);
- void drawIcons(SymbolIconShader&, gl::Context&, PaintMode);
- void drawCollisionBoxes(CollisionBoxShader&, gl::Context&);
const MapMode mode;
- const style::SymbolLayoutProperties layout;
+ const style::SymbolLayoutProperties::Evaluated layout;
const bool sdfIcons;
const bool iconsNeedLinear;
-private:
- friend class SymbolLayout;
-
struct TextBuffer {
- std::vector<SymbolVertex> vertices;
- std::vector<gl::Triangle> triangles;
- std::vector<ElementGroup<SymbolSDFShader>> groups;
+ gl::VertexVector<SymbolVertex> vertices;
+ gl::IndexVector<gl::Triangles> triangles;
+ gl::SegmentVector<SymbolAttributes> segments;
optional<gl::VertexBuffer<SymbolVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
+ optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
} text;
struct IconBuffer {
- std::vector<SymbolVertex> vertices;
- std::vector<gl::Triangle> triangles;
- std::vector<ElementGroup<SymbolSDFShader, SymbolIconShader>> groups;
+ gl::VertexVector<SymbolVertex> vertices;
+ gl::IndexVector<gl::Triangles> triangles;
+ gl::SegmentVector<SymbolAttributes> segments;
optional<gl::VertexBuffer<SymbolVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
+ optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
} icon;
struct CollisionBoxBuffer {
- std::vector<CollisionBoxVertex> vertices;
- std::vector<gl::Line> lines;
- std::vector<ElementGroup<CollisionBoxShader>> groups;
+ gl::VertexVector<CollisionBoxVertex> vertices;
+ gl::IndexVector<gl::Lines> lines;
+ gl::SegmentVector<CollisionBoxAttributes> segments;
optional<gl::VertexBuffer<CollisionBoxVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Line>> indexBuffer;
+ optional<gl::IndexBuffer<gl::Lines>> indexBuffer;
} collisionBox;
};
diff --git a/src/mbgl/shader/circle_shader.cpp b/src/mbgl/shader/circle_shader.cpp
deleted file mode 100644
index 9e294f8d76..0000000000
--- a/src/mbgl/shader/circle_shader.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/shader/circle_shader.hpp>
-#include <mbgl/shader/circle.vertex.hpp>
-#include <mbgl/shader/circle.fragment.hpp>
-#include <mbgl/shader/circle_vertex.hpp>
-
-namespace mbgl {
-
-CircleShader::CircleShader(gl::Context& context, Defines defines)
- : Shader(shaders::circle::name,
- shaders::circle::vertex,
- shaders::circle::fragment,
- context, defines) {
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/circle_shader.hpp b/src/mbgl/shader/circle_shader.hpp
deleted file mode 100644
index c2c4053ba4..0000000000
--- a/src/mbgl/shader/circle_shader.hpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/attribute.hpp>
-#include <mbgl/gl/uniform.hpp>
-#include <mbgl/util/color.hpp>
-
-namespace mbgl {
-
-class CircleVertex;
-
-class CircleShader : public gl::Shader {
-public:
- CircleShader(gl::Context&, Defines defines = None);
-
- using VertexType = CircleVertex;
-
- gl::Attribute<int16_t, 2> a_pos = {"a_pos", *this};
-
- gl::UniformMatrix<4> u_matrix = {"u_matrix", *this};
- gl::Uniform<std::array<float, 2>> u_extrude_scale = {"u_extrude_scale", *this};
- gl::Uniform<float> u_devicepixelratio = {"u_devicepixelratio", *this};
- gl::Uniform<Color> u_color = {"u_color", *this};
- gl::Uniform<float> u_radius = {"u_radius", *this};
- gl::Uniform<float> u_blur = {"u_blur", *this};
- gl::Uniform<float> u_opacity = {"u_opacity", *this};
- gl::Uniform<int32_t> u_scale_with_map = {"u_scale_with_map", *this};
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/circle_vertex.cpp b/src/mbgl/shader/circle_vertex.cpp
deleted file mode 100644
index 8beb88e650..0000000000
--- a/src/mbgl/shader/circle_vertex.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <mbgl/shader/circle_vertex.hpp>
-
-namespace mbgl {
-
-static_assert(sizeof(CircleVertex) == 4, "expected CircleVertex size");
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/circle_vertex.hpp b/src/mbgl/shader/circle_vertex.hpp
deleted file mode 100644
index 4fce49f137..0000000000
--- a/src/mbgl/shader/circle_vertex.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/attribute.hpp>
-
-#include <array>
-#include <cstdint>
-
-namespace mbgl {
-
-class CircleVertex {
-public:
- /*
- * @param {number} x vertex position
- * @param {number} y vertex position
- * @param {number} ex extrude normal
- * @param {number} ey extrude normal
- */
- CircleVertex(int16_t x, int16_t y, float ex, float ey)
- : a_pos {
- static_cast<int16_t>((x * 2) + ((ex + 1) / 2)),
- static_cast<int16_t>((y * 2) + ((ey + 1) / 2))
- } {}
-
- const int16_t a_pos[2];
-};
-
-namespace gl {
-
-template <class Shader>
-struct AttributeBindings<Shader, CircleVertex> {
- std::array<AttributeBinding, 1> operator()(const Shader& shader) {
- return {{
- MBGL_MAKE_ATTRIBUTE_BINDING(CircleVertex, shader, a_pos)
- }};
- };
-};
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/shader/collision_box_shader.cpp b/src/mbgl/shader/collision_box_shader.cpp
deleted file mode 100644
index d61c849cd1..0000000000
--- a/src/mbgl/shader/collision_box_shader.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/shader/collision_box_shader.hpp>
-#include <mbgl/shader/collision_box.vertex.hpp>
-#include <mbgl/shader/collision_box.fragment.hpp>
-#include <mbgl/shader/collision_box_vertex.hpp>
-
-namespace mbgl {
-
-CollisionBoxShader::CollisionBoxShader(gl::Context& context)
- : Shader(shaders::collision_box::name,
- shaders::collision_box::vertex,
- shaders::collision_box::fragment,
- context) {
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/collision_box_shader.hpp b/src/mbgl/shader/collision_box_shader.hpp
deleted file mode 100644
index 2f5c506168..0000000000
--- a/src/mbgl/shader/collision_box_shader.hpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/attribute.hpp>
-#include <mbgl/gl/uniform.hpp>
-
-namespace mbgl {
-
-class CollisionBoxVertex;
-
-class CollisionBoxShader : public gl::Shader {
-public:
- CollisionBoxShader(gl::Context&);
-
- using VertexType = CollisionBoxVertex;
-
- gl::Attribute<int16_t, 2> a_pos = {"a_pos", *this};
- gl::Attribute<int16_t, 2> a_extrude = {"a_extrude", *this};
- gl::Attribute<uint8_t, 2> a_data = {"a_data", *this};
-
- gl::UniformMatrix<4> u_matrix = {"u_matrix", *this};
- gl::Uniform<float> u_scale = {"u_scale", *this};
- gl::Uniform<float> u_zoom = {"u_zoom", *this};
- gl::Uniform<float> u_maxzoom = {"u_maxzoom", *this};
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/collision_box_vertex.cpp b/src/mbgl/shader/collision_box_vertex.cpp
deleted file mode 100644
index 397fbfe6a3..0000000000
--- a/src/mbgl/shader/collision_box_vertex.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <mbgl/shader/collision_box_vertex.hpp>
-
-namespace mbgl {
-
-static_assert(sizeof(CollisionBoxVertex) == 10, "expected CollisionBoxVertex size");
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/collision_box_vertex.hpp b/src/mbgl/shader/collision_box_vertex.hpp
deleted file mode 100644
index ba72b1c0ee..0000000000
--- a/src/mbgl/shader/collision_box_vertex.hpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/attribute.hpp>
-
-#include <array>
-#include <cstdint>
-#include <cmath>
-
-namespace mbgl {
-
-class CollisionBoxVertex {
-public:
- CollisionBoxVertex(int16_t x, int16_t y, float ox, float oy, float maxzoom, float placementZoom)
- : a_pos { x, y },
- a_extrude {
- static_cast<int16_t>(::round(ox)),
- static_cast<int16_t>(::round(oy))
- },
- a_data {
- static_cast<uint8_t>(maxzoom * 10),
- static_cast<uint8_t>(placementZoom * 10)
- } {}
-
- const int16_t a_pos[2];
- const int16_t a_extrude[2];
- const uint8_t a_data[2];
-};
-
-namespace gl {
-
-template <class Shader>
-struct AttributeBindings<Shader, CollisionBoxVertex> {
- std::array<AttributeBinding, 3> operator()(const Shader& shader) {
- return {{
- MBGL_MAKE_ATTRIBUTE_BINDING(CollisionBoxVertex, shader, a_pos),
- MBGL_MAKE_ATTRIBUTE_BINDING(CollisionBoxVertex, shader, a_extrude),
- MBGL_MAKE_ATTRIBUTE_BINDING(CollisionBoxVertex, shader, a_data)
- }};
- };
-};
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/shader/fill_outline_pattern_shader.cpp b/src/mbgl/shader/fill_outline_pattern_shader.cpp
deleted file mode 100644
index b03921d384..0000000000
--- a/src/mbgl/shader/fill_outline_pattern_shader.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/shader/fill_outline_pattern_shader.hpp>
-#include <mbgl/shader/fill_outline_pattern.vertex.hpp>
-#include <mbgl/shader/fill_outline_pattern.fragment.hpp>
-#include <mbgl/shader/fill_vertex.hpp>
-
-namespace mbgl {
-
-FillOutlinePatternShader::FillOutlinePatternShader(gl::Context& context, Defines defines)
- : Shader(shaders::fill_outline_pattern::name,
- shaders::fill_outline_pattern::vertex,
- shaders::fill_outline_pattern::fragment,
- context, defines) {
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/fill_outline_pattern_shader.hpp b/src/mbgl/shader/fill_outline_pattern_shader.hpp
deleted file mode 100644
index 630e6a7ce8..0000000000
--- a/src/mbgl/shader/fill_outline_pattern_shader.hpp
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/attribute.hpp>
-#include <mbgl/gl/uniform.hpp>
-
-namespace mbgl {
-
-class FillVertex;
-
-class FillOutlinePatternShader : public gl::Shader {
-public:
- FillOutlinePatternShader(gl::Context&, Defines defines = None);
-
- using VertexType = FillVertex;
-
- gl::Attribute<int16_t, 2> a_pos = {"a_pos", *this};
-
- gl::UniformMatrix<4> u_matrix = {"u_matrix", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_br_a = {"u_pattern_br_a", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_br_b = {"u_pattern_br_b", *this};
- gl::Uniform<float> u_opacity = {"u_opacity", *this};
- gl::Uniform<float> u_mix = {"u_mix", *this};
- gl::Uniform<float> u_scale_a = {"u_scale_a", *this};
- gl::Uniform<float> u_scale_b = {"u_scale_b", *this};
- gl::Uniform<float> u_tile_units_to_pixels = {"u_tile_units_to_pixels", *this};
- gl::Uniform<int32_t> u_image = {"u_image", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_size_a = {"u_pattern_size_a", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_size_b = {"u_pattern_size_b", *this};
- gl::Uniform<std::array<float, 2>> u_pixel_coord_upper = {"u_pixel_coord_upper", *this};
- gl::Uniform<std::array<float, 2>> u_pixel_coord_lower = {"u_pixel_coord_lower", *this};
- gl::Uniform<std::array<float, 2>> u_world = {"u_world", *this};
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/fill_outline_shader.cpp b/src/mbgl/shader/fill_outline_shader.cpp
deleted file mode 100644
index 6e6d8c2239..0000000000
--- a/src/mbgl/shader/fill_outline_shader.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/shader/fill_outline_shader.hpp>
-#include <mbgl/shader/fill_outline.vertex.hpp>
-#include <mbgl/shader/fill_outline.fragment.hpp>
-#include <mbgl/shader/fill_vertex.hpp>
-
-namespace mbgl {
-
-FillOutlineShader::FillOutlineShader(gl::Context& context, Defines defines)
- : Shader(shaders::fill_outline::name,
- shaders::fill_outline::vertex,
- shaders::fill_outline::fragment,
- context, defines) {
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/fill_outline_shader.hpp b/src/mbgl/shader/fill_outline_shader.hpp
deleted file mode 100644
index c20bc187d3..0000000000
--- a/src/mbgl/shader/fill_outline_shader.hpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/attribute.hpp>
-#include <mbgl/gl/uniform.hpp>
-#include <mbgl/util/color.hpp>
-
-namespace mbgl {
-
-class FillVertex;
-
-class FillOutlineShader : public gl::Shader {
-public:
- FillOutlineShader(gl::Context&, Defines defines = None);
-
- using VertexType = FillVertex;
-
- gl::Attribute<int16_t, 2> a_pos = {"a_pos", *this};
-
- gl::UniformMatrix<4> u_matrix = {"u_matrix", *this};
- gl::Uniform<Color> u_outline_color = {"u_outline_color", *this};
- gl::Uniform<float> u_opacity = {"u_opacity", *this};
- gl::Uniform<std::array<float, 2>> u_world = {"u_world", *this};
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/fill_pattern_shader.cpp b/src/mbgl/shader/fill_pattern_shader.cpp
deleted file mode 100644
index 60be6d79ad..0000000000
--- a/src/mbgl/shader/fill_pattern_shader.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/shader/fill_pattern_shader.hpp>
-#include <mbgl/shader/fill_pattern.vertex.hpp>
-#include <mbgl/shader/fill_pattern.fragment.hpp>
-#include <mbgl/shader/fill_vertex.hpp>
-
-namespace mbgl {
-
-FillPatternShader::FillPatternShader(gl::Context& context, Defines defines)
- : Shader(shaders::fill_pattern::name,
- shaders::fill_pattern::vertex,
- shaders::fill_pattern::fragment,
- context, defines) {
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/fill_pattern_shader.hpp b/src/mbgl/shader/fill_pattern_shader.hpp
deleted file mode 100644
index 36be538000..0000000000
--- a/src/mbgl/shader/fill_pattern_shader.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/attribute.hpp>
-#include <mbgl/gl/uniform.hpp>
-
-namespace mbgl {
-
-class FillVertex;
-
-class FillPatternShader : public gl::Shader {
-public:
- FillPatternShader(gl::Context&, Defines defines = None);
-
- using VertexType = FillVertex;
-
- gl::Attribute<int16_t, 2> a_pos = {"a_pos", *this};
-
- gl::UniformMatrix<4> u_matrix = {"u_matrix", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_br_a = {"u_pattern_br_a", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_br_b = {"u_pattern_br_b", *this};
- gl::Uniform<float> u_opacity = {"u_opacity", *this};
- gl::Uniform<float> u_mix = {"u_mix", *this};
- gl::Uniform<float> u_scale_a = {"u_scale_a", *this};
- gl::Uniform<float> u_scale_b = {"u_scale_b", *this};
- gl::Uniform<float> u_tile_units_to_pixels = {"u_tile_units_to_pixels", *this};
- gl::Uniform<int32_t> u_image = {"u_image", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_size_a = {"u_pattern_size_a", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_size_b = {"u_pattern_size_b", *this};
- gl::Uniform<std::array<float, 2>> u_pixel_coord_upper = {"u_pixel_coord_upper", *this};
- gl::Uniform<std::array<float, 2>> u_pixel_coord_lower = {"u_pixel_coord_lower", *this};
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/fill_shader.cpp b/src/mbgl/shader/fill_shader.cpp
deleted file mode 100644
index 7026bb2f1c..0000000000
--- a/src/mbgl/shader/fill_shader.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/shader/fill_shader.hpp>
-#include <mbgl/shader/fill.vertex.hpp>
-#include <mbgl/shader/fill.fragment.hpp>
-#include <mbgl/shader/fill_vertex.hpp>
-
-namespace mbgl {
-
-FillShader::FillShader(gl::Context& context, Defines defines)
- : Shader(shaders::fill::name,
- shaders::fill::vertex,
- shaders::fill::fragment,
- context, defines) {
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/fill_shader.hpp b/src/mbgl/shader/fill_shader.hpp
deleted file mode 100644
index 1240b73aa2..0000000000
--- a/src/mbgl/shader/fill_shader.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/attribute.hpp>
-#include <mbgl/gl/uniform.hpp>
-#include <mbgl/util/color.hpp>
-
-namespace mbgl {
-
-class FillVertex;
-
-class FillShader : public gl::Shader {
-public:
- FillShader(gl::Context&, Defines defines = None);
-
- using VertexType = FillVertex;
-
- gl::Attribute<int16_t, 2> a_pos = {"a_pos", *this};
-
- gl::UniformMatrix<4> u_matrix = {"u_matrix", *this};
- gl::Uniform<Color> u_color = {"u_color", *this};
- gl::Uniform<float> u_opacity = {"u_opacity", *this};
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/fill_vertex.cpp b/src/mbgl/shader/fill_vertex.cpp
deleted file mode 100644
index c39a0b96b1..0000000000
--- a/src/mbgl/shader/fill_vertex.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <mbgl/shader/fill_vertex.hpp>
-
-namespace mbgl {
-
-static_assert(sizeof(FillVertex) == 4, "expected FillVertex size");
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/fill_vertex.hpp b/src/mbgl/shader/fill_vertex.hpp
deleted file mode 100644
index 1b8130382a..0000000000
--- a/src/mbgl/shader/fill_vertex.hpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/attribute.hpp>
-
-#include <array>
-#include <cstdint>
-
-namespace mbgl {
-
-class FillVertex {
-public:
- FillVertex(int16_t x, int16_t y)
- : a_pos { x, y } {}
-
- const int16_t a_pos[2];
-};
-
-namespace gl {
-
-template <class Shader>
-struct AttributeBindings<Shader, FillVertex> {
- std::array<AttributeBinding, 1> operator()(const Shader& shader) {
- return {{
- MBGL_MAKE_ATTRIBUTE_BINDING(FillVertex, shader, a_pos)
- }};
- };
-};
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/shader/line_pattern_shader.cpp b/src/mbgl/shader/line_pattern_shader.cpp
deleted file mode 100644
index e6bc32a5c9..0000000000
--- a/src/mbgl/shader/line_pattern_shader.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/shader/line_pattern_shader.hpp>
-#include <mbgl/shader/line_pattern.vertex.hpp>
-#include <mbgl/shader/line_pattern.fragment.hpp>
-#include <mbgl/shader/line_vertex.hpp>
-
-namespace mbgl {
-
-LinePatternShader::LinePatternShader(gl::Context& context, Defines defines)
- : Shader(shaders::line_pattern::name,
- shaders::line_pattern::vertex,
- shaders::line_pattern::fragment,
- context, defines) {
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/line_pattern_shader.hpp b/src/mbgl/shader/line_pattern_shader.hpp
deleted file mode 100644
index 1bd6085c8b..0000000000
--- a/src/mbgl/shader/line_pattern_shader.hpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/uniform.hpp>
-#include <mbgl/gl/attribute.hpp>
-
-namespace mbgl {
-
-class LineVertex;
-
-class LinePatternShader : public gl::Shader {
-public:
- LinePatternShader(gl::Context&, Defines defines = None);
-
- using VertexType = LineVertex;
-
- gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this };
- gl::Attribute<uint8_t, 4> a_data = { "a_data", *this };
-
- gl::UniformMatrix<4> u_matrix = {"u_matrix", *this};
- gl::Uniform<float> u_linewidth = {"u_linewidth", *this};
- gl::Uniform<float> u_gapwidth = {"u_gapwidth", *this};
- gl::Uniform<float> u_antialiasing = {"u_antialiasing", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_size_a = {"u_pattern_size_a", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_br_a = {"u_pattern_br_a", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_size_b = {"u_pattern_size_b", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this};
- gl::Uniform<std::array<float, 2>> u_pattern_br_b = {"u_pattern_br_b", *this};
- gl::Uniform<float> u_ratio = {"u_ratio", *this};
- gl::Uniform<float> u_point = {"u_point", *this};
- gl::Uniform<float> u_blur = {"u_blur", *this};
- gl::Uniform<float> u_fade = {"u_fade", *this};
- gl::Uniform<float> u_opacity = {"u_opacity", *this};
- gl::Uniform<float> u_extra = {"u_extra", *this};
- gl::Uniform<float> u_offset = {"u_offset", *this};
- gl::Uniform<int32_t> u_image = {"u_image", *this};
- gl::UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/line_sdf_shader.cpp b/src/mbgl/shader/line_sdf_shader.cpp
deleted file mode 100644
index dd724365ea..0000000000
--- a/src/mbgl/shader/line_sdf_shader.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/shader/line_sdf_shader.hpp>
-#include <mbgl/shader/line_sdf.vertex.hpp>
-#include <mbgl/shader/line_sdf.fragment.hpp>
-#include <mbgl/shader/line_vertex.hpp>
-
-namespace mbgl {
-
-LineSDFShader::LineSDFShader(gl::Context& context, Defines defines)
- : Shader(shaders::line_sdf::name,
- shaders::line_sdf::vertex,
- shaders::line_sdf::fragment,
- context, defines) {
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/line_sdf_shader.hpp b/src/mbgl/shader/line_sdf_shader.hpp
deleted file mode 100644
index d74e42e50f..0000000000
--- a/src/mbgl/shader/line_sdf_shader.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/attribute.hpp>
-#include <mbgl/gl/uniform.hpp>
-#include <mbgl/util/color.hpp>
-
-namespace mbgl {
-
-class LineVertex;
-
-class LineSDFShader : public gl::Shader {
-public:
- LineSDFShader(gl::Context&, Defines defines = None);
-
- using VertexType = LineVertex;
-
- gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this };
- gl::Attribute<uint8_t, 4> a_data = { "a_data", *this };
-
- gl::UniformMatrix<4> u_matrix = {"u_matrix", *this};
- gl::Uniform<Color> u_color = {"u_color", *this};
- gl::Uniform<float> u_opacity = {"u_opacity", *this};
- gl::Uniform<float> u_linewidth = {"u_linewidth", *this};
- gl::Uniform<float> u_gapwidth = {"u_gapwidth", *this};
- gl::Uniform<float> u_antialiasing = {"u_antialiasing", *this};
- gl::Uniform<float> u_ratio = {"u_ratio", *this};
- gl::Uniform<float> u_blur = {"u_blur", *this};
- gl::Uniform<std::array<float, 2>> u_patternscale_a = { "u_patternscale_a", *this};
- gl::Uniform<float> u_tex_y_a = {"u_tex_y_a", *this};
- gl::Uniform<std::array<float, 2>> u_patternscale_b = { "u_patternscale_b", *this};
- gl::Uniform<float> u_tex_y_b = {"u_tex_y_b", *this};
- gl::Uniform<int32_t> u_image = {"u_image", *this};
- gl::Uniform<float> u_sdfgamma = {"u_sdfgamma", *this};
- gl::Uniform<float> u_mix = {"u_mix", *this};
- gl::Uniform<float> u_extra = {"u_extra", *this};
- gl::Uniform<float> u_offset = {"u_offset", *this};
- gl::UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
-};
-
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/line_shader.cpp b/src/mbgl/shader/line_shader.cpp
deleted file mode 100644
index 4e934cd60c..0000000000
--- a/src/mbgl/shader/line_shader.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/shader/line_shader.hpp>
-#include <mbgl/shader/line.vertex.hpp>
-#include <mbgl/shader/line.fragment.hpp>
-#include <mbgl/shader/line_vertex.hpp>
-
-namespace mbgl {
-
-LineShader::LineShader(gl::Context& context, Defines defines)
- : Shader(shaders::line::name,
- shaders::line::vertex,
- shaders::line::fragment,
- context, defines) {
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/line_shader.hpp b/src/mbgl/shader/line_shader.hpp
deleted file mode 100644
index 79991e1883..0000000000
--- a/src/mbgl/shader/line_shader.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/attribute.hpp>
-#include <mbgl/gl/uniform.hpp>
-#include <mbgl/util/color.hpp>
-
-namespace mbgl {
-
-class LineVertex;
-
-class LineShader : public gl::Shader {
-public:
- LineShader(gl::Context&, Defines defines = None);
-
- using VertexType = LineVertex;
-
- gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this };
- gl::Attribute<uint8_t, 4> a_data = { "a_data", *this };
-
- gl::UniformMatrix<4> u_matrix = {"u_matrix", *this};
- gl::Uniform<Color> u_color = {"u_color", *this};
- gl::Uniform<float> u_opacity = {"u_opacity", *this};
- gl::Uniform<float> u_ratio = {"u_ratio", *this};
- gl::Uniform<float> u_linewidth = {"u_linewidth", *this};
- gl::Uniform<float> u_gapwidth = {"u_gapwidth", *this};
- gl::Uniform<float> u_antialiasing = {"u_antialiasing", *this};
- gl::Uniform<float> u_blur = {"u_blur", *this};
- gl::Uniform<float> u_extra = {"u_extra", *this};
- gl::Uniform<float> u_offset = {"u_offset", *this};
- gl::UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
-};
-
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/line_vertex.cpp b/src/mbgl/shader/line_vertex.cpp
deleted file mode 100644
index ad466310d8..0000000000
--- a/src/mbgl/shader/line_vertex.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <mbgl/shader/line_vertex.hpp>
-
-namespace mbgl {
-
-static_assert(sizeof(LineVertex) == 8, "expected LineVertex size");
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/line_vertex.hpp b/src/mbgl/shader/line_vertex.hpp
deleted file mode 100644
index 086100810e..0000000000
--- a/src/mbgl/shader/line_vertex.hpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/attribute.hpp>
-
-#include <array>
-#include <cstdint>
-#include <cmath>
-
-namespace mbgl {
-
-class LineVertex {
-public:
- /*
- * @param {number} x vertex position
- * @param {number} y vertex position
- * @param {number} ex extrude normal
- * @param {number} ey extrude normal
- * @param {number} tx texture normal
- * @param {number} ty texture normal
- * @param {number} dir direction of the line cap (-1/0/1)
- */
- LineVertex(int16_t x, int16_t y, float ex, float ey, bool tx, bool ty, int8_t dir, int32_t linesofar = 0)
- : a_pos {
- static_cast<int16_t>((x * 2) | tx),
- static_cast<int16_t>((y * 2) | ty)
- },
- a_data {
- // add 128 to store an byte in an unsigned byte
- static_cast<uint8_t>(::round(extrudeScale * ex) + 128),
- static_cast<uint8_t>(::round(extrudeScale * ey) + 128),
-
- // Encode the -1/0/1 direction value into the first two bits of .z of a_data.
- // Combine it with the lower 6 bits of `linesofar` (shifted by 2 bites to make
- // room for the direction value). The upper 8 bits of `linesofar` are placed in
- // the `w` component. `linesofar` is scaled down by `LINE_DISTANCE_SCALE` so that
- // we can store longer distances while sacrificing precision.
-
- // Encode the -1/0/1 direction value into .zw coordinates of a_data, which is normally covered
- // by linesofar, so we need to merge them.
- // The z component's first bit, as well as the sign bit is reserved for the direction,
- // so we need to shift the linesofar.
- static_cast<uint8_t>(((dir == 0 ? 0 : (dir < 0 ? -1 : 1 )) + 1) | ((linesofar & 0x3F) << 2)),
- static_cast<uint8_t>(linesofar >> 6)
- } {}
-
- const int16_t a_pos[2];
- const uint8_t a_data[4];
-
- /*
- * Scale the extrusion vector so that the normal length is this value.
- * Contains the "texture" normals (-1..1). This is distinct from the extrude
- * normals for line joins, because the x-value remains 0 for the texture
- * normal array, while the extrude normal actually moves the vertex to create
- * the acute/bevelled line join.
- */
- static const int8_t extrudeScale = 63;
-};
-
-namespace gl {
-
-template <class Shader>
-struct AttributeBindings<Shader, LineVertex> {
- std::array<AttributeBinding, 2> operator()(const Shader& shader) {
- return {{
- MBGL_MAKE_ATTRIBUTE_BINDING(LineVertex, shader, a_pos),
- MBGL_MAKE_ATTRIBUTE_BINDING(LineVertex, shader, a_data)
- }};
- };
-};
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/shader/raster_shader.cpp b/src/mbgl/shader/raster_shader.cpp
deleted file mode 100644
index 34b2bdf47b..0000000000
--- a/src/mbgl/shader/raster_shader.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/shader/raster_shader.hpp>
-#include <mbgl/shader/raster.vertex.hpp>
-#include <mbgl/shader/raster.fragment.hpp>
-#include <mbgl/shader/raster_vertex.hpp>
-
-namespace mbgl {
-
-RasterShader::RasterShader(gl::Context& context, Defines defines)
- : Shader(shaders::raster::name,
- shaders::raster::vertex,
- shaders::raster::fragment,
- context, defines) {
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/raster_shader.hpp b/src/mbgl/shader/raster_shader.hpp
deleted file mode 100644
index 9633fd5fa0..0000000000
--- a/src/mbgl/shader/raster_shader.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/attribute.hpp>
-#include <mbgl/gl/uniform.hpp>
-
-namespace mbgl {
-
-class RasterVertex;
-
-class RasterShader : public gl::Shader {
-public:
- RasterShader(gl::Context&, Defines defines = None);
-
- using VertexType = RasterVertex;
-
- gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this };
- gl::Attribute<uint16_t, 2> a_texture_pos = { "a_texture_pos", *this };
-
- gl::UniformMatrix<4> u_matrix = {"u_matrix", *this};
- gl::Uniform<int32_t> u_image0 = {"u_image0", *this};
- gl::Uniform<int32_t> u_image1 = {"u_image1", *this};
- gl::Uniform<float> u_opacity0 = {"u_opacity0", *this};
- gl::Uniform<float> u_opacity1 = {"u_opacity1", *this};
- gl::Uniform<float> u_buffer_scale = {"u_buffer_scale", *this};
- gl::Uniform<float> u_brightness_low = {"u_brightness_low", *this};
- gl::Uniform<float> u_brightness_high = {"u_brightness_high", *this};
- gl::Uniform<float> u_saturation_factor = {"u_saturation_factor", *this};
- gl::Uniform<float> u_contrast_factor = {"u_contrast_factor", *this};
- gl::Uniform<std::array<float, 3>> u_spin_weights = {"u_spin_weights", *this};
- gl::Uniform<std::array<float, 2>> u_tl_parent = {"u_tl_parent", *this};
- gl::Uniform<float> u_scale_parent = {"u_scale_parent", *this};
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/raster_vertex.cpp b/src/mbgl/shader/raster_vertex.cpp
deleted file mode 100644
index fc9b1f11c2..0000000000
--- a/src/mbgl/shader/raster_vertex.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <mbgl/shader/raster_vertex.hpp>
-
-namespace mbgl {
-
-static_assert(sizeof(RasterVertex) == 8, "expected RasterVertex size");
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/raster_vertex.hpp b/src/mbgl/shader/raster_vertex.hpp
deleted file mode 100644
index 70e08c609d..0000000000
--- a/src/mbgl/shader/raster_vertex.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/attribute.hpp>
-
-#include <array>
-#include <cstdint>
-
-namespace mbgl {
-
-class RasterVertex {
-public:
- RasterVertex(int16_t x, int16_t y, uint16_t tx, uint16_t ty)
- : a_pos {
- x,
- y
- },
- a_texture_pos {
- tx,
- ty
- } {}
-
- const int16_t a_pos[2];
- const uint16_t a_texture_pos[2];
-};
-
-namespace gl {
-
-template <class Shader>
-struct AttributeBindings<Shader, RasterVertex> {
- std::array<AttributeBinding, 2> operator()(const Shader& shader) {
- return {{
- MBGL_MAKE_ATTRIBUTE_BINDING(RasterVertex, shader, a_pos),
- MBGL_MAKE_ATTRIBUTE_BINDING(RasterVertex, shader, a_texture_pos)
- }};
- };
-};
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/shader/shaders.hpp b/src/mbgl/shader/shaders.hpp
deleted file mode 100644
index 937ee85f44..0000000000
--- a/src/mbgl/shader/shaders.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#pragma once
-
-#include <mbgl/shader/circle_shader.hpp>
-#include <mbgl/shader/fill_shader.hpp>
-#include <mbgl/shader/fill_pattern_shader.hpp>
-#include <mbgl/shader/fill_outline_shader.hpp>
-#include <mbgl/shader/fill_outline_pattern_shader.hpp>
-#include <mbgl/shader/line_shader.hpp>
-#include <mbgl/shader/line_sdf_shader.hpp>
-#include <mbgl/shader/line_pattern_shader.hpp>
-#include <mbgl/shader/raster_shader.hpp>
-#include <mbgl/shader/symbol_icon_shader.hpp>
-#include <mbgl/shader/symbol_sdf_shader.hpp>
-
-#include <mbgl/shader/collision_box_shader.hpp>
-
-namespace mbgl {
-
-class Shaders {
-public:
- Shaders(gl::Context& context, gl::Shader::Defines defines = gl::Shader::None)
- : circle(context, defines),
- fill(context, defines),
- fillPattern(context, defines),
- fillOutline(context, defines),
- fillOutlinePattern(context, defines),
- line(context, defines),
- lineSDF(context, defines),
- linePattern(context, defines),
- raster(context, defines),
- symbolIcon(context, defines),
- symbolIconSDF(context, defines),
- symbolGlyph(context, defines),
- collisionBox(context) {
- }
-
- CircleShader circle;
- FillShader fill;
- FillPatternShader fillPattern;
- FillOutlineShader fillOutline;
- FillOutlinePatternShader fillOutlinePattern;
- LineShader line;
- LineSDFShader lineSDF;
- LinePatternShader linePattern;
- RasterShader raster;
- SymbolIconShader symbolIcon;
- SymbolSDFShader symbolIconSDF;
- SymbolSDFShader symbolGlyph;
-
- CollisionBoxShader collisionBox;
-
- gl::VertexArrayObject coveringPlainArray;
- gl::VertexArrayObject coveringRasterArray;
- gl::VertexArrayObject backgroundPatternArray;
- gl::VertexArrayObject backgroundArray;
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/symbol_icon_shader.cpp b/src/mbgl/shader/symbol_icon_shader.cpp
deleted file mode 100644
index 2655a1c9b5..0000000000
--- a/src/mbgl/shader/symbol_icon_shader.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/shader/symbol_icon_shader.hpp>
-#include <mbgl/shader/symbol_icon.vertex.hpp>
-#include <mbgl/shader/symbol_icon.fragment.hpp>
-#include <mbgl/shader/symbol_vertex.hpp>
-
-namespace mbgl {
-
-SymbolIconShader::SymbolIconShader(gl::Context& context, Defines defines)
- : Shader(shaders::symbol_icon::name,
- shaders::symbol_icon::vertex,
- shaders::symbol_icon::fragment,
- context, defines) {
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/symbol_icon_shader.hpp b/src/mbgl/shader/symbol_icon_shader.hpp
deleted file mode 100644
index 5281beb60c..0000000000
--- a/src/mbgl/shader/symbol_icon_shader.hpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/attribute.hpp>
-#include <mbgl/gl/uniform.hpp>
-
-namespace mbgl {
-
-class SymbolVertex;
-
-class SymbolIconShader : public gl::Shader {
-public:
- SymbolIconShader(gl::Context&, Defines defines = None);
-
- using VertexType = SymbolVertex;
-
- gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this };
- gl::Attribute<int16_t, 2> a_offset = { "a_offset", *this };
- gl::Attribute<uint16_t, 2> a_texture_pos = { "a_texture_pos", *this };
- gl::Attribute<uint8_t, 4> a_data = { "a_data", *this };
-
- gl::UniformMatrix<4> u_matrix = {"u_matrix", *this};
- gl::Uniform<std::array<float, 2>> u_extrude_scale = {"u_extrude_scale", *this};
- gl::Uniform<float> u_zoom = {"u_zoom", *this};
- gl::Uniform<float> u_opacity = {"u_opacity", *this};
- gl::Uniform<std::array<float, 2>> u_texsize = {"u_texsize", *this};
- gl::Uniform<int32_t> u_rotate_with_map = {"u_rotate_with_map", *this};
- gl::Uniform<int32_t> u_texture = {"u_texture", *this};
- gl::Uniform<int32_t> u_fadetexture = {"u_fadetexture", *this};
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/symbol_sdf_shader.cpp b/src/mbgl/shader/symbol_sdf_shader.cpp
deleted file mode 100644
index 63c3bd5a4a..0000000000
--- a/src/mbgl/shader/symbol_sdf_shader.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/shader/symbol_sdf_shader.hpp>
-#include <mbgl/shader/symbol_sdf.vertex.hpp>
-#include <mbgl/shader/symbol_sdf.fragment.hpp>
-#include <mbgl/shader/symbol_vertex.hpp>
-
-namespace mbgl {
-
-SymbolSDFShader::SymbolSDFShader(gl::Context& context, Defines defines)
- : Shader(shaders::symbol_sdf::name,
- shaders::symbol_sdf::vertex,
- shaders::symbol_sdf::fragment,
- context, defines) {
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/symbol_sdf_shader.hpp b/src/mbgl/shader/symbol_sdf_shader.hpp
deleted file mode 100644
index 8d3b3df939..0000000000
--- a/src/mbgl/shader/symbol_sdf_shader.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/attribute.hpp>
-#include <mbgl/gl/uniform.hpp>
-#include <mbgl/util/color.hpp>
-
-namespace mbgl {
-
-class SymbolVertex;
-
-class SymbolSDFShader : public gl::Shader {
-public:
- SymbolSDFShader(gl::Context&, Defines defines = None);
-
- using VertexType = SymbolVertex;
-
- gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this };
- gl::Attribute<int16_t, 2> a_offset = { "a_offset", *this };
- gl::Attribute<uint16_t, 2> a_texture_pos = { "a_texture_pos", *this };
- gl::Attribute<uint8_t, 4> a_data = { "a_data", *this };
-
- gl::UniformMatrix<4> u_matrix = {"u_matrix", *this};
- gl::Uniform<std::array<float, 2>> u_extrude_scale = {"u_extrude_scale", *this};
- gl::Uniform<Color> u_color = {"u_color", *this};
- gl::Uniform<float> u_opacity = {"u_opacity", *this};
- gl::Uniform<std::array<float, 2>> u_texsize = {"u_texsize", *this};
- gl::Uniform<float> u_buffer = {"u_buffer", *this};
- gl::Uniform<float> u_gamma = {"u_gamma", *this};
- gl::Uniform<float> u_zoom = {"u_zoom", *this};
- gl::Uniform<float> u_pitch = {"u_pitch", *this};
- gl::Uniform<float> u_bearing = {"u_bearing", *this};
- gl::Uniform<float> u_aspect_ratio = {"u_aspect_ratio", *this};
- gl::Uniform<int32_t> u_rotate_with_map = {"u_rotate_with_map", *this};
- gl::Uniform<int32_t> u_pitch_with_map = {"u_pitch_with_map", *this};
- gl::Uniform<int32_t> u_texture = {"u_texture", *this};
- gl::Uniform<int32_t> u_fadetexture = {"u_fadetexture", *this};
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/symbol_vertex.cpp b/src/mbgl/shader/symbol_vertex.cpp
deleted file mode 100644
index 4075d749ea..0000000000
--- a/src/mbgl/shader/symbol_vertex.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <mbgl/shader/symbol_vertex.hpp>
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/gl.hpp>
-
-namespace mbgl {
-
-static_assert(sizeof(SymbolVertex) == 16, "expected SymbolVertex size");
-
-} // namespace mbgl
diff --git a/src/mbgl/shader/symbol_vertex.hpp b/src/mbgl/shader/symbol_vertex.hpp
deleted file mode 100644
index 4eba86f946..0000000000
--- a/src/mbgl/shader/symbol_vertex.hpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/attribute.hpp>
-
-#include <array>
-#include <cstdint>
-#include <cmath>
-
-namespace mbgl {
-
-class SymbolVertex {
-public:
- SymbolVertex(int16_t x, int16_t y, float ox, float oy, uint16_t tx, uint16_t ty, float minzoom, float maxzoom, float labelminzoom, uint8_t labelangle)
- : a_pos {
- x,
- y
- },
- a_offset {
- static_cast<int16_t>(::round(ox * 64)), // use 1/64 pixels for placement
- static_cast<int16_t>(::round(oy * 64))
- },
- a_texture_pos {
- static_cast<uint16_t>(tx / 4),
- static_cast<uint16_t>(ty / 4)
- },
- a_data {
- static_cast<uint8_t>(labelminzoom * 10), // 1/10 zoom levels: z16 == 160
- static_cast<uint8_t>(labelangle),
- static_cast<uint8_t>(minzoom * 10),
- static_cast<uint8_t>(::fmin(maxzoom, 25) * 10)
- } {}
-
- const int16_t a_pos[2];
- const int16_t a_offset[2];
- const uint16_t a_texture_pos[2];
- const uint8_t a_data[4];
-};
-
-namespace gl {
-
-template <class Shader>
-struct AttributeBindings<Shader, SymbolVertex> {
- std::array<AttributeBinding, 4> operator()(const Shader& shader) {
- return {{
- MBGL_MAKE_ATTRIBUTE_BINDING(SymbolVertex, shader, a_pos),
- MBGL_MAKE_ATTRIBUTE_BINDING(SymbolVertex, shader, a_offset),
- MBGL_MAKE_ATTRIBUTE_BINDING(SymbolVertex, shader, a_texture_pos),
- MBGL_MAKE_ATTRIBUTE_BINDING(SymbolVertex, shader, a_data)
- }};
- };
-};
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/sprite/sprite_atlas.cpp b/src/mbgl/sprite/sprite_atlas.cpp
index 198b0a6c57..ea055ce5ec 100644
--- a/src/mbgl/sprite/sprite_atlas.cpp
+++ b/src/mbgl/sprite/sprite_atlas.cpp
@@ -1,10 +1,9 @@
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/sprite/sprite_atlas_observer.hpp>
#include <mbgl/sprite/sprite_parser.hpp>
-#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/context.hpp>
-#include <mbgl/platform/log.hpp>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/logging.hpp>
+#include <mbgl/util/platform.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/util/constants.hpp>
@@ -28,15 +27,12 @@ struct SpriteAtlas::Loader {
std::unique_ptr<AsyncRequest> spriteRequest;
};
-SpriteAtlas::SpriteAtlas(dimension width_, dimension height_, float pixelRatio_)
- : width(width_),
- height(height_),
- pixelWidth(std::ceil(width * pixelRatio_)),
- pixelHeight(std::ceil(height * pixelRatio_)),
+SpriteAtlas::SpriteAtlas(Size size_, float pixelRatio_)
+ : size(std::move(size_)),
pixelRatio(pixelRatio_),
observer(&nullObserver),
- bin(width_, height_),
- dirtyFlag(true) {
+ bin(size.width, size.height),
+ dirty(true) {
}
SpriteAtlas::~SpriteAtlas() = default;
@@ -128,7 +124,7 @@ void SpriteAtlas::_setSprite(const std::string& name,
auto it = sprites.find(name);
if (it != sprites.end()) {
// There is already a sprite with that name in our store.
- if ((it->second->image.width != sprite->image.width || it->second->image.height != sprite->image.height)) {
+ if (it->second->image.size != sprite->image.size) {
Log::Warning(Event::Sprite, "Can't change sprite dimensions for '%s'", name.c_str());
return;
}
@@ -162,10 +158,10 @@ std::shared_ptr<const SpriteImage> SpriteAtlas::getSprite(const std::string& nam
}
}
-Rect<SpriteAtlas::dimension> SpriteAtlas::allocateImage(const SpriteImage& spriteImage) {
+Rect<uint16_t> SpriteAtlas::allocateImage(const SpriteImage& spriteImage) {
- const uint16_t pixel_width = std::ceil(spriteImage.image.width / pixelRatio);
- const uint16_t pixel_height = std::ceil(spriteImage.image.height / pixelRatio);
+ const uint16_t pixel_width = std::ceil(spriteImage.image.size.width / pixelRatio);
+ const uint16_t pixel_height = std::ceil(spriteImage.image.size.height / pixelRatio);
// Increase to next number divisible by 4, but at least 1.
// This is so we can scale down the texture coordinates and pack them
@@ -175,7 +171,7 @@ Rect<SpriteAtlas::dimension> SpriteAtlas::allocateImage(const SpriteImage& sprit
// We have to allocate a new area in the bin, and store an empty image in it.
// Add a 1px border around every image.
- Rect<dimension> rect = bin.allocate(pack_width, pack_height);
+ Rect<uint16_t> rect = bin.allocate(pack_width, pack_height);
if (rect.w == 0) {
return rect;
}
@@ -197,7 +193,7 @@ optional<SpriteAtlasElement> SpriteAtlas::getImage(const std::string& name,
return {};
}
- Rect<dimension> rect = allocateImage(*sprite);
+ Rect<uint16_t> rect = allocateImage(*sprite);
if (rect.w == 0) {
if (debug::spriteWarnings) {
Log::Warning(Event::Sprite, "sprite atlas bitmap overflow");
@@ -230,8 +226,8 @@ optional<SpriteAtlasPosition> SpriteAtlas::getPosition(const std::string& name,
return SpriteAtlasPosition {
{{ float(spriteImage->getWidth()), spriteImage->getHeight() }},
- {{ float(rect.x + padding) / width, float(rect.y + padding) / height }},
- {{ float(rect.x + padding + w) / width, float(rect.y + padding + h) / height }}
+ {{ float(rect.x + padding) / size.width, float(rect.y + padding) / size.height }},
+ {{ float(rect.x + padding + w) / size.width, float(rect.y + padding + h) / size.height }}
};
}
@@ -264,28 +260,25 @@ void copyBitmap(const uint32_t *src, const uint32_t srcStride, const uint32_t sr
}
void SpriteAtlas::copy(const Holder& holder, const SpritePatternMode mode) {
- if (!data) {
- data = std::make_unique<uint32_t[]>(pixelWidth * pixelHeight);
- std::fill(data.get(), data.get() + pixelWidth * pixelHeight, 0);
+ if (!image.valid()) {
+ image = PremultipliedImage({ static_cast<uint32_t>(std::ceil(size.width * pixelRatio)),
+ static_cast<uint32_t>(std::ceil(size.height * pixelRatio)) });
+ std::fill(image.data.get(), image.data.get() + image.bytes(), 0);
}
- const uint32_t *srcData = reinterpret_cast<const uint32_t *>(holder.spriteImage->image.data.get());
+ const uint32_t* srcData =
+ reinterpret_cast<const uint32_t*>(holder.spriteImage->image.data.get());
if (!srcData) return;
- uint32_t *const dstData = data.get();
+ uint32_t* const dstData = reinterpret_cast<uint32_t*>(image.data.get());
const int padding = 1;
- copyBitmap(srcData, uint32_t(holder.spriteImage->image.width), 0, 0,
- dstData, pixelWidth, (holder.pos.x + padding) * pixelRatio, (holder.pos.y + padding) * pixelRatio, pixelWidth * pixelHeight,
- uint32_t(holder.spriteImage->image.width), uint32_t(holder.spriteImage->image.height), mode);
+ copyBitmap(srcData, holder.spriteImage->image.size.width, 0, 0, dstData, image.size.width,
+ (holder.pos.x + padding) * pixelRatio, (holder.pos.y + padding) * pixelRatio,
+ image.size.width * image.size.height, holder.spriteImage->image.size.width,
+ holder.spriteImage->image.size.height, mode);
- dirtyFlag = true;
-}
-
-void SpriteAtlas::upload(gl::Context& context, gl::TextureUnit unit) {
- if (dirtyFlag) {
- bind(false, context, unit);
- }
+ dirty = true;
}
void SpriteAtlas::updateDirty() {
@@ -316,77 +309,31 @@ void SpriteAtlas::updateDirty() {
dirtySprites.clear();
}
-void SpriteAtlas::bind(bool linear, gl::Context& context, gl::TextureUnit unit) {
- if (!data) {
- return; // Empty atlas
+void SpriteAtlas::upload(gl::Context& context, gl::TextureUnit unit) {
+ if (!texture) {
+ texture = context.createTexture(image, unit);
+ } else if (dirty) {
+ context.updateTexture(*texture, image, unit);
}
- if (!texture) {
- texture = context.createTexture();
- context.activeTexture = unit;
- context.texture[unit] = *texture;
#if not MBGL_USE_GLES2
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
+// if (dirty) {
+// platform::showColorDebugImage("Sprite Atlas",
+// reinterpret_cast<const char*>(image.data.get()), size.width,
+// size.height, image.size.width, image.size.height);
+// }
#endif // MBGL_USE_GLES2
- // We are using clamp to edge here since OpenGL ES doesn't allow GL_REPEAT on NPOT textures.
- // We use those when the pixelRatio isn't a power of two, e.g. on iPhone 6 Plus.
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- fullUploadRequired = true;
- } else if (context.texture[unit] != *texture) {
- context.activeTexture = unit;
- context.texture[unit] = *texture;
- }
- GLuint filter_val = linear ? GL_LINEAR : GL_NEAREST;
- if (filter_val != filter) {
- context.activeTexture = unit;
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_val));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_val));
- filter = filter_val;
- }
-
- if (dirtyFlag) {
- std::lock_guard<std::recursive_mutex> lock(mtx);
-
- context.activeTexture = unit;
- if (fullUploadRequired) {
- MBGL_CHECK_ERROR(glTexImage2D(
- GL_TEXTURE_2D, // GLenum target
- 0, // GLint level
- GL_RGBA, // GLint internalformat
- pixelWidth, // GLsizei width
- pixelHeight, // GLsizei height
- 0, // GLint border
- GL_RGBA, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- data.get() // const GLvoid * data
- ));
- fullUploadRequired = false;
- } else {
- MBGL_CHECK_ERROR(glTexSubImage2D(
- GL_TEXTURE_2D, // GLenum target
- 0, // GLint level
- 0, // GLint xoffset
- 0, // GLint yoffset
- pixelWidth, // GLsizei width
- pixelHeight, // GLsizei height
- GL_RGBA, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- data.get() // const GLvoid *pixels
- ));
- }
-
- dirtyFlag = false;
+ dirty = false;
+}
-#if not MBGL_USE_GLES2
- // platform::showColorDebugImage("Sprite Atlas", reinterpret_cast<const char*>(data.get()),
- // pixelWidth, pixelHeight, pixelWidth, pixelHeight);
-#endif // MBGL_USE_GLES2
- }
+void SpriteAtlas::bind(bool linear, gl::Context& context, gl::TextureUnit unit) {
+ upload(context, unit);
+ context.bindTexture(*texture, unit,
+ linear ? gl::TextureFilter::Linear : gl::TextureFilter::Nearest);
}
-SpriteAtlas::Holder::Holder(std::shared_ptr<const SpriteImage> spriteImage_, Rect<dimension> pos_)
+SpriteAtlas::Holder::Holder(std::shared_ptr<const SpriteImage> spriteImage_, Rect<uint16_t> pos_)
: spriteImage(std::move(spriteImage_)), pos(std::move(pos_)) {
}
diff --git a/src/mbgl/sprite/sprite_atlas.hpp b/src/mbgl/sprite/sprite_atlas.hpp
index 3a0aea2dad..c79aec135e 100644
--- a/src/mbgl/sprite/sprite_atlas.hpp
+++ b/src/mbgl/sprite/sprite_atlas.hpp
@@ -1,7 +1,7 @@
#pragma once
#include <mbgl/geometry/binpack.hpp>
-#include <mbgl/gl/object.hpp>
+#include <mbgl/gl/texture.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/sprite/sprite_image.hpp>
@@ -26,13 +26,15 @@ class Context;
class SpriteImage;
class SpritePosition;
-struct SpriteAtlasPosition {
+class SpriteAtlasPosition {
+public:
std::array<float, 2> size = {{ 0, 0 }};
std::array<float, 2> tl = {{ 0, 0 }};
std::array<float, 2> br = {{ 0, 0 }};
};
-struct SpriteAtlasElement {
+class SpriteAtlasElement {
+public:
Rect<uint16_t> pos;
std::shared_ptr<const SpriteImage> spriteImage;
float relativePixelRatio;
@@ -45,10 +47,9 @@ enum class SpritePatternMode : bool {
class SpriteAtlas : public util::noncopyable {
public:
- typedef uint16_t dimension;
using Sprites = std::map<std::string, std::shared_ptr<const SpriteImage>>;
- SpriteAtlas(dimension width, dimension height, float pixelRatio);
+ SpriteAtlas(Size, float pixelRatio);
~SpriteAtlas();
void load(const std::string& url, FileSource&);
@@ -91,21 +92,19 @@ public:
// the texture is only bound when the data is out of date (=dirty).
void upload(gl::Context&, gl::TextureUnit unit);
- dimension getWidth() const { return width; }
- dimension getHeight() const { return height; }
- dimension getTextureWidth() const { return pixelWidth; }
- dimension getTextureHeight() const { return pixelHeight; }
+ Size getSize() const { return size; }
float getPixelRatio() const { return pixelRatio; }
// Only for use in tests.
- const uint32_t* getData() const { return data.get(); }
+ const PremultipliedImage& getAtlasImage() const {
+ return image;
+ }
private:
void _setSprite(const std::string&, const std::shared_ptr<const SpriteImage>& = nullptr);
void emitSpriteLoadedIfComplete();
- const uint16_t width, height;
- const dimension pixelWidth, pixelHeight;
+ const Size size;
const float pixelRatio;
struct Loader;
@@ -125,26 +124,24 @@ private:
Sprites dirtySprites;
struct Holder : private util::noncopyable {
- Holder(std::shared_ptr<const SpriteImage>, Rect<dimension>);
+ Holder(std::shared_ptr<const SpriteImage>, Rect<uint16_t>);
Holder(Holder&&);
std::shared_ptr<const SpriteImage> spriteImage;
- const Rect<dimension> pos;
+ const Rect<uint16_t> pos;
};
using Key = std::pair<std::string, SpritePatternMode>;
- Rect<SpriteAtlas::dimension> allocateImage(const SpriteImage&);
+ Rect<uint16_t> allocateImage(const SpriteImage&);
void copy(const Holder& holder, SpritePatternMode mode);
std::recursive_mutex mtx;
- BinPack<dimension> bin;
+ BinPack<uint16_t> bin;
std::map<Key, Holder> images;
std::unordered_set<std::string> uninitialized;
- std::unique_ptr<uint32_t[]> data;
- std::atomic<bool> dirtyFlag;
- bool fullUploadRequired = true;
- mbgl::optional<gl::UniqueTexture> texture;
- uint32_t filter = 0;
+ PremultipliedImage image;
+ mbgl::optional<gl::Texture> texture;
+ std::atomic<bool> dirty;
static const int buffer = 1;
};
diff --git a/src/mbgl/sprite/sprite_image.cpp b/src/mbgl/sprite/sprite_image.cpp
index d7e422ed1d..1579d9d89e 100644
--- a/src/mbgl/sprite/sprite_image.cpp
+++ b/src/mbgl/sprite/sprite_image.cpp
@@ -13,7 +13,7 @@ SpriteImage::SpriteImage(PremultipliedImage&& image_,
pixelRatio(pixelRatio_),
sdf(sdf_) {
- if (image.size() == 0) {
+ if (!image.valid()) {
throw util::SpriteImageException("Sprite image dimensions may not be zero");
} else if (pixelRatio <= 0) {
throw util::SpriteImageException("Sprite pixelRatio may not be <= 0");
diff --git a/src/mbgl/sprite/sprite_parser.cpp b/src/mbgl/sprite/sprite_parser.cpp
index 34b1d875b6..9de8515e14 100644
--- a/src/mbgl/sprite/sprite_parser.cpp
+++ b/src/mbgl/sprite/sprite_parser.cpp
@@ -1,10 +1,11 @@
#include <mbgl/sprite/sprite_parser.hpp>
#include <mbgl/sprite/sprite_image.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/rapidjson.hpp>
+#include <mbgl/util/string.hpp>
#include <cmath>
#include <limits>
@@ -13,30 +14,34 @@
namespace mbgl {
SpriteImagePtr createSpriteImage(const PremultipliedImage& image,
- const uint16_t srcX,
- const uint16_t srcY,
- const uint16_t width,
- const uint16_t height,
+ const uint32_t srcX,
+ const uint32_t srcY,
+ const uint32_t width,
+ const uint32_t height,
const double ratio,
const bool sdf) {
// Disallow invalid parameter configurations.
if (width <= 0 || height <= 0 || width > 1024 || height > 1024 ||
ratio <= 0 || ratio > 10 ||
- srcX + width > image.width || srcY + height > image.height) {
- Log::Error(Event::Sprite, "Can't create sprite with invalid metrics");
+ srcX >= image.size.width || srcY >= image.size.height ||
+ srcX + width > image.size.width || srcY + height > image.size.height) {
+ Log::Error(Event::Sprite, "Can't create sprite with invalid metrics: %ux%u@%u,%u in %ux%u@%sx sprite",
+ width, height, srcX, srcY,
+ image.size.width, image.size.height,
+ util::toString(ratio).c_str());
return nullptr;
}
- PremultipliedImage dstImage(width, height);
+ PremultipliedImage dstImage({ width, height });
auto srcData = reinterpret_cast<const uint32_t*>(image.data.get());
auto dstData = reinterpret_cast<uint32_t*>(dstImage.data.get());
// Copy from the source image into our individual sprite image
- for (uint16_t y = 0; y < height; ++y) {
+ for (uint32_t y = 0; y < height; ++y) {
const auto dstRow = y * width;
- const auto srcRow = (y + srcY) * image.width + srcX;
- for (uint16_t x = 0; x < width; ++x) {
+ const auto srcRow = (y + srcY) * image.size.width + srcX;
+ for (uint32_t x = 0; x < width; ++x) {
dstData[dstRow + x] = srcData[srcRow + x];
}
}
diff --git a/src/mbgl/sprite/sprite_parser.hpp b/src/mbgl/sprite/sprite_parser.hpp
index 6a564ce330..4a63d4858a 100644
--- a/src/mbgl/sprite/sprite_parser.hpp
+++ b/src/mbgl/sprite/sprite_parser.hpp
@@ -17,10 +17,10 @@ using SpriteImagePtr = std::shared_ptr<const SpriteImage>;
// Extracts an individual image from a spritesheet from the given location.
SpriteImagePtr createSpriteImage(const PremultipliedImage&,
- uint16_t srcX,
- uint16_t srcY,
- uint16_t srcWidth,
- uint16_t srcHeight,
+ uint32_t srcX,
+ uint32_t srcY,
+ uint32_t srcWidth,
+ uint32_t srcHeight,
double ratio,
bool sdf);
diff --git a/src/mbgl/style/bucket_parameters.cpp b/src/mbgl/style/bucket_parameters.cpp
index 64f53babcd..e641120c5e 100644
--- a/src/mbgl/style/bucket_parameters.cpp
+++ b/src/mbgl/style/bucket_parameters.cpp
@@ -6,7 +6,8 @@ namespace mbgl {
namespace style {
void BucketParameters::eachFilteredFeature(const Filter& filter,
- std::function<void (const GeometryTileFeature&, std::size_t index, const std::string& layerName)> function) {
+ const GeometryTileLayer& layer,
+ std::function<void (const GeometryTileFeature&, std::size_t index, const std::string& layerName)> function) {
auto name = layer.getName();
for (std::size_t i = 0; !cancelled() && i < layer.featureCount(); i++) {
auto feature = layer.getFeature(i);
diff --git a/src/mbgl/style/bucket_parameters.hpp b/src/mbgl/style/bucket_parameters.hpp
index 9aad35dcad..d5e05c5dd2 100644
--- a/src/mbgl/style/bucket_parameters.hpp
+++ b/src/mbgl/style/bucket_parameters.hpp
@@ -9,45 +9,26 @@
namespace mbgl {
-class TileID;
class GeometryTileLayer;
class GeometryTileFeature;
-class GlyphAtlas;
-class CollisionTile;
class FeatureIndex;
namespace style {
class BucketParameters {
public:
- BucketParameters(const OverscaledTileID& tileID_,
- const GeometryTileLayer& layer_,
- const std::atomic<bool>& obsolete_,
- uintptr_t tileUID_,
- GlyphAtlas& glyphAtlas_,
- FeatureIndex& featureIndex_,
- const MapMode mode_)
- : tileID(tileID_),
- layer(layer_),
- obsolete(obsolete_),
- tileUID(tileUID_),
- glyphAtlas(glyphAtlas_),
- featureIndex(featureIndex_),
- mode(mode_) {}
+ const OverscaledTileID& tileID;
+ const std::atomic<bool>& obsolete;
+ FeatureIndex& featureIndex;
+ const MapMode mode;
bool cancelled() const {
return obsolete;
}
- void eachFilteredFeature(const Filter&, std::function<void (const GeometryTileFeature&, std::size_t index, const std::string& layerName)>);
-
- const OverscaledTileID& tileID;
- const GeometryTileLayer& layer;
- const std::atomic<bool>& obsolete;
- uintptr_t tileUID;
- GlyphAtlas& glyphAtlas;
- FeatureIndex& featureIndex;
- const MapMode mode;
+ void eachFilteredFeature(const Filter&,
+ const GeometryTileLayer&,
+ std::function<void (const GeometryTileFeature&, std::size_t index, const std::string& layerName)>);
};
} // namespace style
diff --git a/src/mbgl/style/class_dictionary.hpp b/src/mbgl/style/class_dictionary.hpp
index e609fb5303..37eb488240 100644
--- a/src/mbgl/style/class_dictionary.hpp
+++ b/src/mbgl/style/class_dictionary.hpp
@@ -9,7 +9,6 @@ namespace mbgl {
namespace style {
enum class ClassID : uint32_t {
- Fallback = 0, // These values are from the fallback properties
Default = 1, // These values are from the default style for a layer
Named = 2 // These values (and all subsequent IDs) are from a named style from the layer
};
diff --git a/src/mbgl/style/conversion/stringify.hpp b/src/mbgl/style/conversion/stringify.hpp
new file mode 100644
index 0000000000..d06b2f2814
--- /dev/null
+++ b/src/mbgl/style/conversion/stringify.hpp
@@ -0,0 +1,256 @@
+#pragma once
+
+#include <mbgl/style/filter.hpp>
+#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/layout_property.hpp>
+#include <mbgl/util/enum.hpp>
+#include <mbgl/util/color.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/ignore.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+#include <array>
+#include <vector>
+#include <unordered_map>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <class Writer>
+void stringify(Writer& writer, NullValue) {
+ writer.Null();
+}
+
+template <class Writer>
+void stringify(Writer& writer, bool v) {
+ writer.Bool(v);
+}
+
+template <class Writer>
+void stringify(Writer& writer, uint64_t v) {
+ writer.Uint64(v);
+}
+
+template <class Writer>
+void stringify(Writer& writer, int64_t v) {
+ writer.Int64(v);
+}
+
+template <class Writer>
+void stringify(Writer& writer, double v) {
+ writer.Double(v);
+}
+
+template <class Writer>
+void stringify(Writer& writer, const std::string& v) {
+ writer.String(v);
+}
+
+template <class Writer, class T, class Enable = std::enable_if_t<std::is_enum<T>::value>>
+void stringify(Writer& writer, const T& v) {
+ writer.String(Enum<T>::toString(v));
+}
+
+template <class Writer>
+void stringify(Writer& writer, const Color& v) {
+ writer.String(v.stringify());
+}
+
+template <class Writer>
+void stringify(Writer& writer, const std::array<float, 2>& v) {
+ writer.StartArray();
+ writer.Double(v[0]);
+ writer.Double(v[1]);
+ writer.EndArray();
+}
+
+template <class Writer>
+void stringify(Writer& writer, const std::array<float, 4>& v) {
+ writer.StartArray();
+ writer.Double(v[0]);
+ writer.Double(v[1]);
+ writer.Double(v[2]);
+ writer.Double(v[3]);
+ writer.EndArray();
+}
+
+template <class Writer>
+void stringify(Writer&, const Value&);
+
+template <class Writer, class T>
+void stringify(Writer& writer, const std::vector<T>& v) {
+ writer.StartArray();
+ for (const auto& e : v) {
+ stringify(writer, e);
+ }
+ writer.EndArray();
+}
+
+template <class Writer, class T>
+void stringify(Writer& writer, const std::unordered_map<std::string, T>& m) {
+ writer.StartObject();
+ for (const auto& p : m) {
+ writer.Key(p.first.data(), static_cast<unsigned>(p.first.size()));
+ stringify(writer, p.second);
+ }
+ writer.EndObject();
+}
+
+template <class Writer>
+void stringify(Writer& writer, const Value& v) {
+ Value::visit(v, [&] (const auto& v_) { stringify(writer, v_); });
+}
+
+template <class Writer>
+class StringifyFilter {
+public:
+ Writer& writer;
+
+ void operator()(const NullFilter&) {
+ writer.Null();
+ }
+
+ void operator()(const EqualsFilter& f) {
+ stringifyBinaryFilter(f, "==");
+ }
+
+ void operator()(const NotEqualsFilter& f) {
+ stringifyBinaryFilter(f, "!=");
+ }
+
+ void operator()(const LessThanFilter& f) {
+ stringifyBinaryFilter(f, "<");
+ }
+
+ void operator()(const LessThanEqualsFilter& f) {
+ stringifyBinaryFilter(f, "<=");
+ }
+
+ void operator()(const GreaterThanFilter& f) {
+ stringifyBinaryFilter(f, ">");
+ }
+
+ void operator()(const GreaterThanEqualsFilter& f) {
+ stringifyBinaryFilter(f, ">=");
+ }
+
+ void operator()(const InFilter& f) {
+ stringifySetFilter(f, "in");
+ }
+
+ void operator()(const NotInFilter& f) {
+ stringifySetFilter(f, "!in");
+ }
+
+ void operator()(const AllFilter& f) {
+ stringifyCompoundFilter(f, "all");
+ }
+
+ void operator()(const AnyFilter& f) {
+ stringifyCompoundFilter(f, "any");
+ }
+
+ void operator()(const NoneFilter& f) {
+ stringifyCompoundFilter(f, "none");
+ }
+
+ void operator()(const HasFilter& f) {
+ stringifyUnaryFilter(f, "has");
+ }
+
+ void operator()(const NotHasFilter& f) {
+ stringifyUnaryFilter(f, "!has");
+ }
+
+private:
+ template <class F>
+ void stringifyBinaryFilter(const F& f, const char * op) {
+ writer.StartArray();
+ writer.String(op);
+ writer.String(f.key);
+ stringify(writer, f.value);
+ writer.EndArray();
+ }
+
+ template <class F>
+ void stringifySetFilter(const F& f, const char * op) {
+ writer.StartArray();
+ writer.String(op);
+ writer.String(f.key);
+ for (const auto& value : f.values) {
+ stringify(writer, value);
+ }
+ writer.EndArray();
+ }
+
+ template <class F>
+ void stringifyCompoundFilter(const F& f, const char * op) {
+ writer.StartArray();
+ writer.String(op);
+ for (const auto& filter : f.filters) {
+ Filter::visit(filter, *this);
+ }
+ writer.EndArray();
+ }
+
+ template <class F>
+ void stringifyUnaryFilter(const F& f, const char * op) {
+ writer.StartArray();
+ writer.String(op);
+ writer.String(f.key);
+ writer.EndArray();
+ }
+};
+
+template <class Writer>
+void stringify(Writer& writer, const Filter& f) {
+ Filter::visit(f, StringifyFilter<Writer> { writer });
+}
+
+template <class Writer>
+void stringify(Writer& writer, const Undefined&) {
+ assert(false); // Should be omitted entirely instead.
+ writer.Null();
+}
+
+template <class Writer, class T>
+void stringify(Writer& writer, const Function<T>& f) {
+ writer.StartObject();
+ writer.Key("base");
+ writer.Double(f.getBase());
+ writer.Key("stops");
+ writer.StartArray();
+ for (const auto& stop : f.getStops()) {
+ writer.StartArray();
+ writer.Double(stop.first);
+ stringify(writer, stop.second);
+ writer.EndArray();
+ }
+ writer.EndArray();
+ writer.EndObject();
+}
+
+template <class Writer, class T>
+void stringify(Writer& writer, const PropertyValue<T>& v) {
+ v.evaluate([&] (const auto& v_) { stringify(writer, v_); });
+}
+
+template <class Property, class Writer, class T>
+void stringify(Writer& writer, const PropertyValue<T>& value) {
+ if (value) {
+ writer.Key(Property::key);
+ stringify(writer, value);
+ }
+}
+
+template <class Writer, class... Ps>
+void stringify(Writer& writer, const LayoutProperties<Ps...>& ps) {
+ writer.StartObject();
+ util::ignore({ (stringify<Ps>(writer, ps.unevaluated.template get<Ps>()), 0)... });
+ writer.EndObject();
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/cross_faded_property_evaluator.cpp b/src/mbgl/style/cross_faded_property_evaluator.cpp
new file mode 100644
index 0000000000..4de939576e
--- /dev/null
+++ b/src/mbgl/style/cross_faded_property_evaluator.cpp
@@ -0,0 +1,53 @@
+#include <mbgl/style/cross_faded_property_evaluator.hpp>
+#include <mbgl/util/chrono.hpp>
+
+#include <cmath>
+
+namespace mbgl {
+namespace style {
+
+template <typename T>
+Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const Undefined&) const {
+ return calculate(defaultValue, defaultValue, defaultValue);
+}
+
+template <typename T>
+Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const T& constant) const {
+ return calculate(constant, constant, constant);
+}
+
+template <typename T>
+T getBiggestStopLessThan(const Function<T>& function, float z) {
+ const auto& stops = function.getStops();
+ for (uint32_t i = 0; i < stops.size(); i++) {
+ if (stops[i].first > z) {
+ return stops[i == 0 ? i : i - 1].second;
+ }
+ }
+ return stops.at(stops.size() - 1).second;
+}
+
+template <typename T>
+Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const Function<T>& function) const {
+ return calculate(getBiggestStopLessThan(function, parameters.z - 1.0f),
+ getBiggestStopLessThan(function, parameters.z),
+ getBiggestStopLessThan(function, parameters.z + 1.0f));
+}
+
+template <typename T>
+Faded<T> CrossFadedPropertyEvaluator<T>::calculate(const T& min, const T& mid, const T& max) const {
+ const float z = parameters.z;
+ const float fraction = z - std::floor(z);
+ const std::chrono::duration<float> d = parameters.defaultFadeDuration;
+ const float t = std::min((parameters.now - parameters.zoomHistory.lastIntegerZoomTime) / d, 1.0f);
+
+ return z > parameters.zoomHistory.lastIntegerZoom
+ ? Faded<T> { min, mid, 2.0f, 1.0f, fraction + (1.0f - fraction) * t }
+ : Faded<T> { max, mid, 0.5f, 1.0f, 1 - (1 - t) * fraction };
+}
+
+template class CrossFadedPropertyEvaluator<std::string>;
+template class CrossFadedPropertyEvaluator<std::vector<float>>;
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/cross_faded_property_evaluator.hpp b/src/mbgl/style/cross_faded_property_evaluator.hpp
new file mode 100644
index 0000000000..70c8c0c978
--- /dev/null
+++ b/src/mbgl/style/cross_faded_property_evaluator.hpp
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/property_evaluation_parameters.hpp>
+#include <mbgl/util/interpolate.hpp>
+
+namespace mbgl {
+namespace style {
+
+template <typename T>
+class Faded {
+public:
+ T from;
+ T to;
+ float fromScale;
+ float toScale;
+ float t;
+};
+
+template <typename T>
+class CrossFadedPropertyEvaluator {
+public:
+ using ResultType = Faded<T>;
+
+ CrossFadedPropertyEvaluator(const PropertyEvaluationParameters& parameters_, T defaultValue_)
+ : parameters(parameters_),
+ defaultValue(std::move(defaultValue_)) {}
+
+ Faded<T> operator()(const Undefined&) const;
+ Faded<T> operator()(const T& constant) const;
+ Faded<T> operator()(const Function<T>&) const;
+
+private:
+ Faded<T> calculate(const T& min, const T& mid, const T& max) const;
+
+ const PropertyEvaluationParameters& parameters;
+ T defaultValue;
+};
+
+} // namespace style
+
+namespace util {
+template <typename T>
+struct Interpolator<style::Faded<T>>
+ : Uninterpolated {};
+} // namespace util
+
+} // namespace mbgl
diff --git a/src/mbgl/style/function.cpp b/src/mbgl/style/function.cpp
new file mode 100644
index 0000000000..02750c7d2e
--- /dev/null
+++ b/src/mbgl/style/function.cpp
@@ -0,0 +1,81 @@
+#include <mbgl/style/function.hpp>
+#include <mbgl/style/types.hpp>
+#include <mbgl/util/color.hpp>
+#include <mbgl/util/interpolate.hpp>
+
+#include <cmath>
+
+namespace mbgl {
+namespace style {
+
+template <typename T>
+T Function<T>::evaluate(float z) const {
+ bool smaller = false;
+ float smaller_z = 0.0f;
+ T smaller_val = T();
+ bool larger = false;
+ float larger_z = 0.0f;
+ T larger_val = T();
+
+ for (uint32_t i = 0; i < stops.size(); i++) {
+ float stop_z = stops[i].first;
+ T stop_val = stops[i].second;
+ if (stop_z <= z && (!smaller || smaller_z < stop_z)) {
+ smaller = true;
+ smaller_z = stop_z;
+ smaller_val = stop_val;
+ }
+ if (stop_z >= z && (!larger || larger_z > stop_z)) {
+ larger = true;
+ larger_z = stop_z;
+ larger_val = stop_val;
+ }
+ }
+
+ if (smaller && larger) {
+ if (larger_z == smaller_z || larger_val == smaller_val) {
+ return smaller_val;
+ }
+ const float zoomDiff = larger_z - smaller_z;
+ const float zoomProgress = z - smaller_z;
+ if (base == 1.0f) {
+ const float t = zoomProgress / zoomDiff;
+ return util::interpolate(smaller_val, larger_val, t);
+ } else {
+ const float t = (std::pow(base, zoomProgress) - 1) / (std::pow(base, zoomDiff) - 1);
+ return util::interpolate(smaller_val, larger_val, t);
+ }
+ } else if (larger) {
+ return larger_val;
+ } else if (smaller) {
+ return smaller_val;
+ } else {
+ // No stop defined.
+ assert(false);
+ return T();
+ }
+}
+
+template class Function<bool>;
+template class Function<float>;
+template class Function<Color>;
+template class Function<std::vector<float>>;
+template class Function<std::vector<std::string>>;
+template class Function<std::array<float, 2>>;
+template class Function<std::array<float, 4>>;
+
+template class Function<std::string>;
+template class Function<TranslateAnchorType>;
+template class Function<RotateAnchorType>;
+template class Function<CirclePitchScaleType>;
+template class Function<LineCapType>;
+template class Function<LineJoinType>;
+template class Function<SymbolPlacementType>;
+template class Function<TextAnchorType>;
+template class Function<TextJustifyType>;
+template class Function<TextTransformType>;
+template class Function<AlignmentType>;
+template class Function<IconTextFitType>;
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/group_by_layout.cpp b/src/mbgl/style/group_by_layout.cpp
new file mode 100644
index 0000000000..b15fe1ca0d
--- /dev/null
+++ b/src/mbgl/style/group_by_layout.cpp
@@ -0,0 +1,50 @@
+#include <mbgl/style/group_by_layout.hpp>
+#include <mbgl/style/layer.hpp>
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+#include <rapidjson/writer.h>
+#include <rapidjson/stringbuffer.h>
+
+#include <unordered_map>
+
+namespace mbgl {
+namespace style {
+
+std::string layoutKey(const Layer& layer) {
+ using namespace conversion;
+
+ rapidjson::StringBuffer s;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(s);
+
+ writer.StartArray();
+ writer.Uint(static_cast<uint32_t>(layer.type));
+ writer.String(layer.baseImpl->source);
+ writer.String(layer.baseImpl->sourceLayer);
+ writer.Double(layer.baseImpl->minZoom);
+ writer.Double(layer.baseImpl->maxZoom);
+ writer.Uint(static_cast<uint32_t>(layer.baseImpl->visibility));
+ stringify(writer, layer.baseImpl->filter);
+ layer.baseImpl->stringifyLayout(writer);
+ writer.EndArray();
+
+ return s.GetString();
+}
+
+std::vector<std::vector<const Layer*>> groupByLayout(const std::vector<std::unique_ptr<Layer>>& layers) {
+ std::unordered_map<std::string, std::vector<const Layer*>> map;
+ for (auto& layer : layers) {
+ map[layoutKey(*layer)].push_back(layer.get());
+ }
+
+ std::vector<std::vector<const Layer*>> result;
+ for (auto& pair : map) {
+ result.push_back(pair.second);
+ }
+
+ return result;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/group_by_layout.hpp b/src/mbgl/style/group_by_layout.hpp
new file mode 100644
index 0000000000..3a89ac95f3
--- /dev/null
+++ b/src/mbgl/style/group_by_layout.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <vector>
+#include <memory>
+
+namespace mbgl {
+namespace style {
+
+class Layer;
+
+std::vector<std::vector<const Layer*>> groupByLayout(const std::vector<std::unique_ptr<Layer>>&);
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layer_impl.cpp b/src/mbgl/style/layer_impl.cpp
index 7a0195c55c..5840318724 100644
--- a/src/mbgl/style/layer_impl.cpp
+++ b/src/mbgl/style/layer_impl.cpp
@@ -4,19 +4,13 @@ namespace mbgl {
namespace style {
std::unique_ptr<Layer> Layer::Impl::copy(const std::string& id_,
- const std::string& ref_,
const std::string& source_) const {
std::unique_ptr<Layer> result = clone();
result->baseImpl->id = id_;
- result->baseImpl->ref = ref_;
result->baseImpl->source = source_;
return result;
}
-const std::string& Layer::Impl::bucketName() const {
- return ref.empty() ? id : ref;
-}
-
bool Layer::Impl::hasRenderPass(RenderPass pass) const {
return bool(passes & pass);
}
diff --git a/src/mbgl/style/layer_impl.hpp b/src/mbgl/style/layer_impl.hpp
index 4bf2956a6d..0fea70c10b 100644
--- a/src/mbgl/style/layer_impl.hpp
+++ b/src/mbgl/style/layer_impl.hpp
@@ -8,6 +8,9 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
+#include <rapidjson/writer.h>
+#include <rapidjson/stringbuffer.h>
+
#include <memory>
#include <string>
#include <limits>
@@ -19,7 +22,7 @@ class Bucket;
namespace style {
class CascadeParameters;
-class CalculationParameters;
+class PropertyEvaluationParameters;
class BucketParameters;
/**
@@ -37,29 +40,28 @@ class Layer::Impl {
public:
virtual ~Impl() = default;
- // Create a new layer with the specified `id`, `ref`, and `sourceID`. All other properties
+ // Create a new layer with the specified `id` and `sourceID`. All other properties
// are copied from this layer.
std::unique_ptr<Layer> copy(const std::string& id,
- const std::string& ref,
const std::string& sourceID) const;
// Create an identical copy of this layer.
virtual std::unique_ptr<Layer> clone() const = 0;
- // Create a layer, copying all properties except id, ref, and paint properties from this layer.
+ // Create a layer, copying all properties except id and paint properties from this layer.
virtual std::unique_ptr<Layer> cloneRef(const std::string& id) const = 0;
- // If the layer has a ref, the ref. Otherwise, the id.
- const std::string& bucketName() const;
+ // Utility function for automatic layer grouping.
+ virtual void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const = 0;
// Partially evaluate paint properties based on a set of classes.
virtual void cascade(const CascadeParameters&) = 0;
// Fully evaluate cascaded paint properties based on a zoom level.
// Returns true if any paint properties have active transitions.
- virtual bool recalculate(const CalculationParameters&) = 0;
+ virtual bool evaluate(const PropertyEvaluationParameters&) = 0;
- virtual std::unique_ptr<Bucket> createBucket(BucketParameters&) const = 0;
+ virtual std::unique_ptr<Bucket> createBucket(BucketParameters&, const GeometryTileLayer&) const = 0;
// Checks whether this layer needs to be rendered in the given render pass.
bool hasRenderPass(RenderPass) const;
@@ -78,7 +80,6 @@ public:
public:
std::string id;
- std::string ref;
std::string source;
std::string sourceLayer;
Filter filter;
diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp
index 5e5faf37e6..a75038bfa0 100644
--- a/src/mbgl/style/layers/background_layer.cpp
+++ b/src/mbgl/style/layers/background_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/background_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -26,11 +27,13 @@ std::unique_ptr<Layer> BackgroundLayer::Impl::clone() const {
std::unique_ptr<Layer> BackgroundLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<BackgroundLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = BackgroundPaintProperties();
return std::move(result);
}
+void BackgroundLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+
// Layout properties
@@ -42,13 +45,13 @@ PropertyValue<Color> BackgroundLayer::getDefaultBackgroundColor() {
}
PropertyValue<Color> BackgroundLayer::getBackgroundColor(const optional<std::string>& klass) const {
- return impl->paint.backgroundColor.get(klass);
+ return impl->paint.get<BackgroundColor>(klass);
}
void BackgroundLayer::setBackgroundColor(PropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getBackgroundColor(klass))
return;
- impl->paint.backgroundColor.set(value, klass);
+ impl->paint.set<BackgroundColor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -57,13 +60,13 @@ PropertyValue<std::string> BackgroundLayer::getDefaultBackgroundPattern() {
}
PropertyValue<std::string> BackgroundLayer::getBackgroundPattern(const optional<std::string>& klass) const {
- return impl->paint.backgroundPattern.get(klass);
+ return impl->paint.get<BackgroundPattern>(klass);
}
void BackgroundLayer::setBackgroundPattern(PropertyValue<std::string> value, const optional<std::string>& klass) {
if (value == getBackgroundPattern(klass))
return;
- impl->paint.backgroundPattern.set(value, klass);
+ impl->paint.set<BackgroundPattern>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -72,13 +75,13 @@ PropertyValue<float> BackgroundLayer::getDefaultBackgroundOpacity() {
}
PropertyValue<float> BackgroundLayer::getBackgroundOpacity(const optional<std::string>& klass) const {
- return impl->paint.backgroundOpacity.get(klass);
+ return impl->paint.get<BackgroundOpacity>(klass);
}
void BackgroundLayer::setBackgroundOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getBackgroundOpacity(klass))
return;
- impl->paint.backgroundOpacity.set(value, klass);
+ impl->paint.set<BackgroundOpacity>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
diff --git a/src/mbgl/style/layers/background_layer_impl.cpp b/src/mbgl/style/layers/background_layer_impl.cpp
index ea389b828e..4a8fe39c9a 100644
--- a/src/mbgl/style/layers/background_layer_impl.cpp
+++ b/src/mbgl/style/layers/background_layer_impl.cpp
@@ -8,15 +8,15 @@ void BackgroundLayer::Impl::cascade(const CascadeParameters& parameters) {
paint.cascade(parameters);
}
-bool BackgroundLayer::Impl::recalculate(const CalculationParameters& parameters) {
- bool hasTransitions = paint.recalculate(parameters);
+bool BackgroundLayer::Impl::evaluate(const PropertyEvaluationParameters& parameters) {
+ paint.evaluate(parameters);
- passes = paint.backgroundOpacity > 0 ? RenderPass::Translucent : RenderPass::None;
+ passes = paint.evaluated.get<BackgroundOpacity>() > 0 ? RenderPass::Translucent : RenderPass::None;
- return hasTransitions;
+ return paint.hasTransition();
}
-std::unique_ptr<Bucket> BackgroundLayer::Impl::createBucket(BucketParameters&) const {
+std::unique_ptr<Bucket> BackgroundLayer::Impl::createBucket(BucketParameters&, const GeometryTileLayer&) const {
return nullptr;
}
diff --git a/src/mbgl/style/layers/background_layer_impl.hpp b/src/mbgl/style/layers/background_layer_impl.hpp
index abbb740f42..4629217e6d 100644
--- a/src/mbgl/style/layers/background_layer_impl.hpp
+++ b/src/mbgl/style/layers/background_layer_impl.hpp
@@ -11,11 +11,12 @@ class BackgroundLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
- bool recalculate(const CalculationParameters&) override;
+ bool evaluate(const PropertyEvaluationParameters&) override;
- std::unique_ptr<Bucket> createBucket(BucketParameters&) const override;
+ std::unique_ptr<Bucket> createBucket(BucketParameters&, const GeometryTileLayer&) const override;
BackgroundPaintProperties paint;
};
diff --git a/src/mbgl/style/layers/background_layer_properties.cpp b/src/mbgl/style/layers/background_layer_properties.cpp
index 558093a255..ba3e638977 100644
--- a/src/mbgl/style/layers/background_layer_properties.cpp
+++ b/src/mbgl/style/layers/background_layer_properties.cpp
@@ -5,21 +5,5 @@
namespace mbgl {
namespace style {
-void BackgroundPaintProperties::cascade(const CascadeParameters& parameters) {
- backgroundColor.cascade(parameters);
- backgroundPattern.cascade(parameters);
- backgroundOpacity.cascade(parameters);
-}
-
-bool BackgroundPaintProperties::recalculate(const CalculationParameters& parameters) {
- bool hasTransitions = false;
-
- hasTransitions |= backgroundColor.calculate(parameters);
- hasTransitions |= backgroundPattern.calculate(parameters);
- hasTransitions |= backgroundOpacity.calculate(parameters);
-
- return hasTransitions;
-}
-
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/background_layer_properties.hpp b/src/mbgl/style/layers/background_layer_properties.hpp
index 78a35a4f0c..792bf3de94 100644
--- a/src/mbgl/style/layers/background_layer_properties.hpp
+++ b/src/mbgl/style/layers/background_layer_properties.hpp
@@ -9,18 +9,23 @@
namespace mbgl {
namespace style {
-class CascadeParameters;
-class CalculationParameters;
+struct BackgroundColor : PaintProperty<Color> {
+ static Color defaultValue() { return Color::black(); }
+};
-class BackgroundPaintProperties {
-public:
- void cascade(const CascadeParameters&);
- bool recalculate(const CalculationParameters&);
+struct BackgroundPattern : CrossFadedPaintProperty<std::string> {
+ static std::string defaultValue() { return ""; }
+};
- PaintProperty<Color> backgroundColor { Color::black() };
- PaintProperty<std::string, CrossFadedPropertyEvaluator> backgroundPattern { "" };
- PaintProperty<float> backgroundOpacity { 1 };
+struct BackgroundOpacity : PaintProperty<float> {
+ static float defaultValue() { return 1; }
};
+class BackgroundPaintProperties : public PaintProperties<
+ BackgroundColor,
+ BackgroundPattern,
+ BackgroundOpacity
+> {};
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp
index a2b8d316d6..389ab93403 100644
--- a/src/mbgl/style/layers/circle_layer.cpp
+++ b/src/mbgl/style/layers/circle_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/circle_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -27,11 +28,13 @@ std::unique_ptr<Layer> CircleLayer::Impl::clone() const {
std::unique_ptr<Layer> CircleLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<CircleLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = CirclePaintProperties();
return std::move(result);
}
+void CircleLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+
// Source
const std::string& CircleLayer::getSourceID() const {
@@ -67,13 +70,13 @@ PropertyValue<float> CircleLayer::getDefaultCircleRadius() {
}
PropertyValue<float> CircleLayer::getCircleRadius(const optional<std::string>& klass) const {
- return impl->paint.circleRadius.get(klass);
+ return impl->paint.get<CircleRadius>(klass);
}
void CircleLayer::setCircleRadius(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getCircleRadius(klass))
return;
- impl->paint.circleRadius.set(value, klass);
+ impl->paint.set<CircleRadius>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -82,13 +85,13 @@ PropertyValue<Color> CircleLayer::getDefaultCircleColor() {
}
PropertyValue<Color> CircleLayer::getCircleColor(const optional<std::string>& klass) const {
- return impl->paint.circleColor.get(klass);
+ return impl->paint.get<CircleColor>(klass);
}
void CircleLayer::setCircleColor(PropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getCircleColor(klass))
return;
- impl->paint.circleColor.set(value, klass);
+ impl->paint.set<CircleColor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -97,13 +100,13 @@ PropertyValue<float> CircleLayer::getDefaultCircleBlur() {
}
PropertyValue<float> CircleLayer::getCircleBlur(const optional<std::string>& klass) const {
- return impl->paint.circleBlur.get(klass);
+ return impl->paint.get<CircleBlur>(klass);
}
void CircleLayer::setCircleBlur(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getCircleBlur(klass))
return;
- impl->paint.circleBlur.set(value, klass);
+ impl->paint.set<CircleBlur>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -112,13 +115,13 @@ PropertyValue<float> CircleLayer::getDefaultCircleOpacity() {
}
PropertyValue<float> CircleLayer::getCircleOpacity(const optional<std::string>& klass) const {
- return impl->paint.circleOpacity.get(klass);
+ return impl->paint.get<CircleOpacity>(klass);
}
void CircleLayer::setCircleOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getCircleOpacity(klass))
return;
- impl->paint.circleOpacity.set(value, klass);
+ impl->paint.set<CircleOpacity>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -127,13 +130,13 @@ PropertyValue<std::array<float, 2>> CircleLayer::getDefaultCircleTranslate() {
}
PropertyValue<std::array<float, 2>> CircleLayer::getCircleTranslate(const optional<std::string>& klass) const {
- return impl->paint.circleTranslate.get(klass);
+ return impl->paint.get<CircleTranslate>(klass);
}
void CircleLayer::setCircleTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) {
if (value == getCircleTranslate(klass))
return;
- impl->paint.circleTranslate.set(value, klass);
+ impl->paint.set<CircleTranslate>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -142,13 +145,13 @@ PropertyValue<TranslateAnchorType> CircleLayer::getDefaultCircleTranslateAnchor(
}
PropertyValue<TranslateAnchorType> CircleLayer::getCircleTranslateAnchor(const optional<std::string>& klass) const {
- return impl->paint.circleTranslateAnchor.get(klass);
+ return impl->paint.get<CircleTranslateAnchor>(klass);
}
void CircleLayer::setCircleTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) {
if (value == getCircleTranslateAnchor(klass))
return;
- impl->paint.circleTranslateAnchor.set(value, klass);
+ impl->paint.set<CircleTranslateAnchor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -157,13 +160,58 @@ PropertyValue<CirclePitchScaleType> CircleLayer::getDefaultCirclePitchScale() {
}
PropertyValue<CirclePitchScaleType> CircleLayer::getCirclePitchScale(const optional<std::string>& klass) const {
- return impl->paint.circlePitchScale.get(klass);
+ return impl->paint.get<CirclePitchScale>(klass);
}
void CircleLayer::setCirclePitchScale(PropertyValue<CirclePitchScaleType> value, const optional<std::string>& klass) {
if (value == getCirclePitchScale(klass))
return;
- impl->paint.circlePitchScale.set(value, klass);
+ impl->paint.set<CirclePitchScale>(value, klass);
+ impl->observer->onLayerPaintPropertyChanged(*this);
+}
+
+PropertyValue<float> CircleLayer::getDefaultCircleStrokeWidth() {
+ return { 0 };
+}
+
+PropertyValue<float> CircleLayer::getCircleStrokeWidth(const optional<std::string>& klass) const {
+ return impl->paint.get<CircleStrokeWidth>(klass);
+}
+
+void CircleLayer::setCircleStrokeWidth(PropertyValue<float> value, const optional<std::string>& klass) {
+ if (value == getCircleStrokeWidth(klass))
+ return;
+ impl->paint.set<CircleStrokeWidth>(value, klass);
+ impl->observer->onLayerPaintPropertyChanged(*this);
+}
+
+PropertyValue<Color> CircleLayer::getDefaultCircleStrokeColor() {
+ return { Color::black() };
+}
+
+PropertyValue<Color> CircleLayer::getCircleStrokeColor(const optional<std::string>& klass) const {
+ return impl->paint.get<CircleStrokeColor>(klass);
+}
+
+void CircleLayer::setCircleStrokeColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+ if (value == getCircleStrokeColor(klass))
+ return;
+ impl->paint.set<CircleStrokeColor>(value, klass);
+ impl->observer->onLayerPaintPropertyChanged(*this);
+}
+
+PropertyValue<float> CircleLayer::getDefaultCircleStrokeOpacity() {
+ return { 1 };
+}
+
+PropertyValue<float> CircleLayer::getCircleStrokeOpacity(const optional<std::string>& klass) const {
+ return impl->paint.get<CircleStrokeOpacity>(klass);
+}
+
+void CircleLayer::setCircleStrokeOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+ if (value == getCircleStrokeOpacity(klass))
+ return;
+ impl->paint.set<CircleStrokeOpacity>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
diff --git a/src/mbgl/style/layers/circle_layer_impl.cpp b/src/mbgl/style/layers/circle_layer_impl.cpp
index 33699b6665..136522e41c 100644
--- a/src/mbgl/style/layers/circle_layer_impl.cpp
+++ b/src/mbgl/style/layers/circle_layer_impl.cpp
@@ -12,31 +12,30 @@ void CircleLayer::Impl::cascade(const CascadeParameters& parameters) {
paint.cascade(parameters);
}
-bool CircleLayer::Impl::recalculate(const CalculationParameters& parameters) {
- bool hasTransitions = paint.recalculate(parameters);
+bool CircleLayer::Impl::evaluate(const PropertyEvaluationParameters& parameters) {
+ paint.evaluate(parameters);
- passes = (paint.circleRadius > 0 && paint.circleColor.value.a > 0 && paint.circleOpacity > 0)
+ passes = (paint.evaluated.get<CircleRadius>() > 0 && paint.evaluated.get<CircleColor>().a > 0 && paint.evaluated.get<CircleOpacity>() > 0)
? RenderPass::Translucent : RenderPass::None;
- return hasTransitions;
+ return paint.hasTransition();
}
-std::unique_ptr<Bucket> CircleLayer::Impl::createBucket(BucketParameters& parameters) const {
+std::unique_ptr<Bucket> CircleLayer::Impl::createBucket(BucketParameters& parameters, const GeometryTileLayer& layer) const {
auto bucket = std::make_unique<CircleBucket>(parameters.mode);
- auto& name = bucketName();
- parameters.eachFilteredFeature(filter, [&] (const auto& feature, std::size_t index, const std::string& layerName) {
+ parameters.eachFilteredFeature(filter, layer, [&] (const auto& feature, std::size_t index, const std::string& layerName) {
auto geometries = feature.getGeometries();
bucket->addGeometry(geometries);
- parameters.featureIndex.insert(geometries, index, layerName, name);
+ parameters.featureIndex.insert(geometries, index, layerName, id);
});
return std::move(bucket);
}
float CircleLayer::Impl::getQueryRadius() const {
- const std::array<float, 2>& translate = paint.circleTranslate;
- return paint.circleRadius + util::length(translate[0], translate[1]);
+ const std::array<float, 2>& translate = paint.evaluated.get<CircleTranslate>();
+ return paint.evaluated.get<CircleRadius>() + util::length(translate[0], translate[1]);
}
bool CircleLayer::Impl::queryIntersectsGeometry(
@@ -46,9 +45,9 @@ bool CircleLayer::Impl::queryIntersectsGeometry(
const float pixelsToTileUnits) const {
auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
- queryGeometry, paint.circleTranslate, paint.circleTranslateAnchor, bearing, pixelsToTileUnits);
+ queryGeometry, paint.evaluated.get<CircleTranslate>(), paint.evaluated.get<CircleTranslateAnchor>(), bearing, pixelsToTileUnits);
- auto circleRadius = paint.circleRadius * pixelsToTileUnits;
+ auto circleRadius = paint.evaluated.get<CircleRadius>() * pixelsToTileUnits;
return util::polygonIntersectsBufferedMultiPoint(
translatedQueryGeometry.value_or(queryGeometry), geometry, circleRadius);
diff --git a/src/mbgl/style/layers/circle_layer_impl.hpp b/src/mbgl/style/layers/circle_layer_impl.hpp
index 14baaf84e4..744a56898c 100644
--- a/src/mbgl/style/layers/circle_layer_impl.hpp
+++ b/src/mbgl/style/layers/circle_layer_impl.hpp
@@ -11,11 +11,12 @@ class CircleLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
- bool recalculate(const CalculationParameters&) override;
+ bool evaluate(const PropertyEvaluationParameters&) override;
- std::unique_ptr<Bucket> createBucket(BucketParameters&) const override;
+ std::unique_ptr<Bucket> createBucket(BucketParameters&, const GeometryTileLayer&) const override;
float getQueryRadius() const override;
bool queryIntersectsGeometry(
diff --git a/src/mbgl/style/layers/circle_layer_properties.cpp b/src/mbgl/style/layers/circle_layer_properties.cpp
index 7243cf87f4..af727fa36f 100644
--- a/src/mbgl/style/layers/circle_layer_properties.cpp
+++ b/src/mbgl/style/layers/circle_layer_properties.cpp
@@ -5,29 +5,5 @@
namespace mbgl {
namespace style {
-void CirclePaintProperties::cascade(const CascadeParameters& parameters) {
- circleRadius.cascade(parameters);
- circleColor.cascade(parameters);
- circleBlur.cascade(parameters);
- circleOpacity.cascade(parameters);
- circleTranslate.cascade(parameters);
- circleTranslateAnchor.cascade(parameters);
- circlePitchScale.cascade(parameters);
-}
-
-bool CirclePaintProperties::recalculate(const CalculationParameters& parameters) {
- bool hasTransitions = false;
-
- hasTransitions |= circleRadius.calculate(parameters);
- hasTransitions |= circleColor.calculate(parameters);
- hasTransitions |= circleBlur.calculate(parameters);
- hasTransitions |= circleOpacity.calculate(parameters);
- hasTransitions |= circleTranslate.calculate(parameters);
- hasTransitions |= circleTranslateAnchor.calculate(parameters);
- hasTransitions |= circlePitchScale.calculate(parameters);
-
- return hasTransitions;
-}
-
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/circle_layer_properties.hpp b/src/mbgl/style/layers/circle_layer_properties.hpp
index 0166bc8be4..ea36b31949 100644
--- a/src/mbgl/style/layers/circle_layer_properties.hpp
+++ b/src/mbgl/style/layers/circle_layer_properties.hpp
@@ -9,22 +9,58 @@
namespace mbgl {
namespace style {
-class CascadeParameters;
-class CalculationParameters;
-
-class CirclePaintProperties {
-public:
- void cascade(const CascadeParameters&);
- bool recalculate(const CalculationParameters&);
-
- PaintProperty<float> circleRadius { 5 };
- PaintProperty<Color> circleColor { Color::black() };
- PaintProperty<float> circleBlur { 0 };
- PaintProperty<float> circleOpacity { 1 };
- PaintProperty<std::array<float, 2>> circleTranslate { {{ 0, 0 }} };
- PaintProperty<TranslateAnchorType> circleTranslateAnchor { TranslateAnchorType::Map };
- PaintProperty<CirclePitchScaleType> circlePitchScale { CirclePitchScaleType::Map };
+struct CircleRadius : PaintProperty<float> {
+ static float defaultValue() { return 5; }
};
+struct CircleColor : PaintProperty<Color> {
+ static Color defaultValue() { return Color::black(); }
+};
+
+struct CircleBlur : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct CircleOpacity : PaintProperty<float> {
+ static float defaultValue() { return 1; }
+};
+
+struct CircleTranslate : PaintProperty<std::array<float, 2>> {
+ static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+};
+
+struct CircleTranslateAnchor : PaintProperty<TranslateAnchorType> {
+ static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; }
+};
+
+struct CirclePitchScale : PaintProperty<CirclePitchScaleType> {
+ static CirclePitchScaleType defaultValue() { return CirclePitchScaleType::Map; }
+};
+
+struct CircleStrokeWidth : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct CircleStrokeColor : PaintProperty<Color> {
+ static Color defaultValue() { return Color::black(); }
+};
+
+struct CircleStrokeOpacity : PaintProperty<float> {
+ static float defaultValue() { return 1; }
+};
+
+class CirclePaintProperties : public PaintProperties<
+ CircleRadius,
+ CircleColor,
+ CircleBlur,
+ CircleOpacity,
+ CircleTranslate,
+ CircleTranslateAnchor,
+ CirclePitchScale,
+ CircleStrokeWidth,
+ CircleStrokeColor,
+ CircleStrokeOpacity
+> {};
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/custom_layer_impl.cpp b/src/mbgl/style/layers/custom_layer_impl.cpp
index 8896d04ca1..cecd60a296 100644
--- a/src/mbgl/style/layers/custom_layer_impl.cpp
+++ b/src/mbgl/style/layers/custom_layer_impl.cpp
@@ -34,6 +34,9 @@ std::unique_ptr<Layer> CustomLayer::Impl::cloneRef(const std::string&) const {
return std::make_unique<CustomLayer>(*this);
}
+void CustomLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+
void CustomLayer::Impl::initialize() {
assert(initializeFn);
initializeFn(context);
@@ -50,24 +53,24 @@ void CustomLayer::Impl::render(const TransformState& state) const {
CustomLayerRenderParameters parameters;
- parameters.width = state.getWidth();
- parameters.height = state.getHeight();
+ parameters.width = state.getSize().width;
+ parameters.height = state.getSize().height;
parameters.latitude = state.getLatLng().latitude;
parameters.longitude = state.getLatLng().longitude;
parameters.zoom = state.getZoom();
parameters.bearing = -state.getAngle() * util::RAD2DEG;
parameters.pitch = state.getPitch();
- parameters.altitude = state.getAltitude();
+ parameters.fieldOfView = state.getFieldOfView();
renderFn(context, parameters);
}
-bool CustomLayer::Impl::recalculate(const CalculationParameters&) {
+bool CustomLayer::Impl::evaluate(const PropertyEvaluationParameters&) {
passes = RenderPass::Translucent;
return false;
}
-std::unique_ptr<Bucket> CustomLayer::Impl::createBucket(BucketParameters&) const {
+std::unique_ptr<Bucket> CustomLayer::Impl::createBucket(BucketParameters&, const GeometryTileLayer&) const {
return nullptr;
}
diff --git a/src/mbgl/style/layers/custom_layer_impl.hpp b/src/mbgl/style/layers/custom_layer_impl.hpp
index b5b626ca5e..71fb46d0d9 100644
--- a/src/mbgl/style/layers/custom_layer_impl.hpp
+++ b/src/mbgl/style/layers/custom_layer_impl.hpp
@@ -27,11 +27,12 @@ public:
private:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) final {}
- bool recalculate(const CalculationParameters&) final;
+ bool evaluate(const PropertyEvaluationParameters&) final;
- std::unique_ptr<Bucket> createBucket(BucketParameters&) const final;
+ std::unique_ptr<Bucket> createBucket(BucketParameters&, const GeometryTileLayer&) const final;
CustomLayerInitializeFunction initializeFn = nullptr;
CustomLayerRenderFunction renderFn = nullptr;
diff --git a/src/mbgl/style/layers/fill_extrusion_layer.cpp b/src/mbgl/style/layers/fill_extrusion_layer.cpp
new file mode 100644
index 0000000000..34f0267d16
--- /dev/null
+++ b/src/mbgl/style/layers/fill_extrusion_layer.cpp
@@ -0,0 +1,174 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
+
+namespace mbgl {
+namespace style {
+
+FillExtrusionLayer::FillExtrusionLayer(const std::string& layerID, const std::string& sourceID)
+ : Layer(Type::FillExtrusion, std::make_unique<Impl>())
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+ impl->id = layerID;
+ impl->source = sourceID;
+}
+
+FillExtrusionLayer::FillExtrusionLayer(const Impl& other)
+ : Layer(Type::FillExtrusion, std::make_unique<Impl>(other))
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+}
+
+FillExtrusionLayer::~FillExtrusionLayer() = default;
+
+std::unique_ptr<Layer> FillExtrusionLayer::Impl::clone() const {
+ return std::make_unique<FillExtrusionLayer>(*this);
+}
+
+std::unique_ptr<Layer> FillExtrusionLayer::Impl::cloneRef(const std::string& id_) const {
+ auto result = std::make_unique<FillExtrusionLayer>(*this);
+ result->impl->id = id_;
+ result->impl->paint = FillExtrusionPaintProperties();
+ return std::move(result);
+}
+
+void FillExtrusionLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+
+// Source
+
+const std::string& FillExtrusionLayer::getSourceID() const {
+ return impl->source;
+}
+
+void FillExtrusionLayer::setSourceLayer(const std::string& sourceLayer) {
+ impl->sourceLayer = sourceLayer;
+}
+
+const std::string& FillExtrusionLayer::getSourceLayer() const {
+ return impl->sourceLayer;
+}
+
+// Filter
+
+void FillExtrusionLayer::setFilter(const Filter& filter) {
+ impl->filter = filter;
+ impl->observer->onLayerFilterChanged(*this);
+}
+
+const Filter& FillExtrusionLayer::getFilter() const {
+ return impl->filter;
+}
+
+// Layout properties
+
+
+// Paint properties
+
+PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionOpacity() {
+ return { 1 };
+}
+
+PropertyValue<float> FillExtrusionLayer::getFillExtrusionOpacity(const optional<std::string>& klass) const {
+ return impl->paint.get<FillExtrusionOpacity>(klass);
+}
+
+void FillExtrusionLayer::setFillExtrusionOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+ if (value == getFillExtrusionOpacity(klass))
+ return;
+ impl->paint.set<FillExtrusionOpacity>(value, klass);
+ impl->observer->onLayerPaintPropertyChanged(*this);
+}
+
+PropertyValue<Color> FillExtrusionLayer::getDefaultFillExtrusionColor() {
+ return { Color::black() };
+}
+
+PropertyValue<Color> FillExtrusionLayer::getFillExtrusionColor(const optional<std::string>& klass) const {
+ return impl->paint.get<FillExtrusionColor>(klass);
+}
+
+void FillExtrusionLayer::setFillExtrusionColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+ if (value == getFillExtrusionColor(klass))
+ return;
+ impl->paint.set<FillExtrusionColor>(value, klass);
+ impl->observer->onLayerPaintPropertyChanged(*this);
+}
+
+PropertyValue<std::array<float, 2>> FillExtrusionLayer::getDefaultFillExtrusionTranslate() {
+ return { {{ 0, 0 }} };
+}
+
+PropertyValue<std::array<float, 2>> FillExtrusionLayer::getFillExtrusionTranslate(const optional<std::string>& klass) const {
+ return impl->paint.get<FillExtrusionTranslate>(klass);
+}
+
+void FillExtrusionLayer::setFillExtrusionTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) {
+ if (value == getFillExtrusionTranslate(klass))
+ return;
+ impl->paint.set<FillExtrusionTranslate>(value, klass);
+ impl->observer->onLayerPaintPropertyChanged(*this);
+}
+
+PropertyValue<TranslateAnchorType> FillExtrusionLayer::getDefaultFillExtrusionTranslateAnchor() {
+ return { TranslateAnchorType::Map };
+}
+
+PropertyValue<TranslateAnchorType> FillExtrusionLayer::getFillExtrusionTranslateAnchor(const optional<std::string>& klass) const {
+ return impl->paint.get<FillExtrusionTranslateAnchor>(klass);
+}
+
+void FillExtrusionLayer::setFillExtrusionTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) {
+ if (value == getFillExtrusionTranslateAnchor(klass))
+ return;
+ impl->paint.set<FillExtrusionTranslateAnchor>(value, klass);
+ impl->observer->onLayerPaintPropertyChanged(*this);
+}
+
+PropertyValue<std::string> FillExtrusionLayer::getDefaultFillExtrusionPattern() {
+ return { "" };
+}
+
+PropertyValue<std::string> FillExtrusionLayer::getFillExtrusionPattern(const optional<std::string>& klass) const {
+ return impl->paint.get<FillExtrusionPattern>(klass);
+}
+
+void FillExtrusionLayer::setFillExtrusionPattern(PropertyValue<std::string> value, const optional<std::string>& klass) {
+ if (value == getFillExtrusionPattern(klass))
+ return;
+ impl->paint.set<FillExtrusionPattern>(value, klass);
+ impl->observer->onLayerPaintPropertyChanged(*this);
+}
+
+PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionHeight() {
+ return { 0 };
+}
+
+PropertyValue<float> FillExtrusionLayer::getFillExtrusionHeight(const optional<std::string>& klass) const {
+ return impl->paint.get<FillExtrusionHeight>(klass);
+}
+
+void FillExtrusionLayer::setFillExtrusionHeight(PropertyValue<float> value, const optional<std::string>& klass) {
+ if (value == getFillExtrusionHeight(klass))
+ return;
+ impl->paint.set<FillExtrusionHeight>(value, klass);
+ impl->observer->onLayerPaintPropertyChanged(*this);
+}
+
+PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionBase() {
+ return { 0 };
+}
+
+PropertyValue<float> FillExtrusionLayer::getFillExtrusionBase(const optional<std::string>& klass) const {
+ return impl->paint.get<FillExtrusionBase>(klass);
+}
+
+void FillExtrusionLayer::setFillExtrusionBase(PropertyValue<float> value, const optional<std::string>& klass) {
+ if (value == getFillExtrusionBase(klass))
+ return;
+ impl->paint.set<FillExtrusionBase>(value, klass);
+ impl->observer->onLayerPaintPropertyChanged(*this);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_extrusion_layer_impl.cpp b/src/mbgl/style/layers/fill_extrusion_layer_impl.cpp
new file mode 100644
index 0000000000..ebe9009312
--- /dev/null
+++ b/src/mbgl/style/layers/fill_extrusion_layer_impl.cpp
@@ -0,0 +1,19 @@
+#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
+#include <mbgl/renderer/bucket.hpp>
+
+namespace mbgl {
+namespace style {
+
+void FillExtrusionLayer::Impl::cascade(const CascadeParameters&) {
+}
+
+bool FillExtrusionLayer::Impl::evaluate(const PropertyEvaluationParameters&) {
+ return false;
+}
+
+std::unique_ptr<Bucket> FillExtrusionLayer::Impl::createBucket(BucketParameters&, const GeometryTileLayer&) const {
+ return nullptr;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp b/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp
new file mode 100644
index 0000000000..3dd8bb270a
--- /dev/null
+++ b/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+class FillExtrusionLayer::Impl : public Layer::Impl {
+public:
+ std::unique_ptr<Layer> clone() const override;
+ std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
+
+ void cascade(const CascadeParameters&) override;
+ bool evaluate(const PropertyEvaluationParameters&) override;
+
+ std::unique_ptr<Bucket> createBucket(BucketParameters&, const GeometryTileLayer&) const override;
+
+ FillExtrusionPaintProperties paint;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_extrusion_layer_properties.cpp b/src/mbgl/style/layers/fill_extrusion_layer_properties.cpp
new file mode 100644
index 0000000000..59572bd3ab
--- /dev/null
+++ b/src/mbgl/style/layers/fill_extrusion_layer_properties.cpp
@@ -0,0 +1,9 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/fill_extrusion_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp b/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp
new file mode 100644
index 0000000000..a2d01199a5
--- /dev/null
+++ b/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp
@@ -0,0 +1,51 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#pragma once
+
+#include <mbgl/style/types.hpp>
+#include <mbgl/style/layout_property.hpp>
+#include <mbgl/style/paint_property.hpp>
+
+namespace mbgl {
+namespace style {
+
+struct FillExtrusionOpacity : PaintProperty<float> {
+ static float defaultValue() { return 1; }
+};
+
+struct FillExtrusionColor : PaintProperty<Color> {
+ static Color defaultValue() { return Color::black(); }
+};
+
+struct FillExtrusionTranslate : PaintProperty<std::array<float, 2>> {
+ static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+};
+
+struct FillExtrusionTranslateAnchor : PaintProperty<TranslateAnchorType> {
+ static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; }
+};
+
+struct FillExtrusionPattern : CrossFadedPaintProperty<std::string> {
+ static std::string defaultValue() { return ""; }
+};
+
+struct FillExtrusionHeight : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct FillExtrusionBase : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+class FillExtrusionPaintProperties : public PaintProperties<
+ FillExtrusionOpacity,
+ FillExtrusionColor,
+ FillExtrusionTranslate,
+ FillExtrusionTranslateAnchor,
+ FillExtrusionPattern,
+ FillExtrusionHeight,
+ FillExtrusionBase
+> {};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp
index c61de81d1a..b8fa8cad8b 100644
--- a/src/mbgl/style/layers/fill_layer.cpp
+++ b/src/mbgl/style/layers/fill_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -27,11 +28,13 @@ std::unique_ptr<Layer> FillLayer::Impl::clone() const {
std::unique_ptr<Layer> FillLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<FillLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = FillPaintProperties();
return std::move(result);
}
+void FillLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+
// Source
const std::string& FillLayer::getSourceID() const {
@@ -67,13 +70,13 @@ PropertyValue<bool> FillLayer::getDefaultFillAntialias() {
}
PropertyValue<bool> FillLayer::getFillAntialias(const optional<std::string>& klass) const {
- return impl->paint.fillAntialias.get(klass);
+ return impl->paint.get<FillAntialias>(klass);
}
void FillLayer::setFillAntialias(PropertyValue<bool> value, const optional<std::string>& klass) {
if (value == getFillAntialias(klass))
return;
- impl->paint.fillAntialias.set(value, klass);
+ impl->paint.set<FillAntialias>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -82,13 +85,13 @@ PropertyValue<float> FillLayer::getDefaultFillOpacity() {
}
PropertyValue<float> FillLayer::getFillOpacity(const optional<std::string>& klass) const {
- return impl->paint.fillOpacity.get(klass);
+ return impl->paint.get<FillOpacity>(klass);
}
void FillLayer::setFillOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getFillOpacity(klass))
return;
- impl->paint.fillOpacity.set(value, klass);
+ impl->paint.set<FillOpacity>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -97,13 +100,13 @@ PropertyValue<Color> FillLayer::getDefaultFillColor() {
}
PropertyValue<Color> FillLayer::getFillColor(const optional<std::string>& klass) const {
- return impl->paint.fillColor.get(klass);
+ return impl->paint.get<FillColor>(klass);
}
void FillLayer::setFillColor(PropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getFillColor(klass))
return;
- impl->paint.fillColor.set(value, klass);
+ impl->paint.set<FillColor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -112,13 +115,13 @@ PropertyValue<Color> FillLayer::getDefaultFillOutlineColor() {
}
PropertyValue<Color> FillLayer::getFillOutlineColor(const optional<std::string>& klass) const {
- return impl->paint.fillOutlineColor.get(klass);
+ return impl->paint.get<FillOutlineColor>(klass);
}
void FillLayer::setFillOutlineColor(PropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getFillOutlineColor(klass))
return;
- impl->paint.fillOutlineColor.set(value, klass);
+ impl->paint.set<FillOutlineColor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -127,13 +130,13 @@ PropertyValue<std::array<float, 2>> FillLayer::getDefaultFillTranslate() {
}
PropertyValue<std::array<float, 2>> FillLayer::getFillTranslate(const optional<std::string>& klass) const {
- return impl->paint.fillTranslate.get(klass);
+ return impl->paint.get<FillTranslate>(klass);
}
void FillLayer::setFillTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) {
if (value == getFillTranslate(klass))
return;
- impl->paint.fillTranslate.set(value, klass);
+ impl->paint.set<FillTranslate>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -142,13 +145,13 @@ PropertyValue<TranslateAnchorType> FillLayer::getDefaultFillTranslateAnchor() {
}
PropertyValue<TranslateAnchorType> FillLayer::getFillTranslateAnchor(const optional<std::string>& klass) const {
- return impl->paint.fillTranslateAnchor.get(klass);
+ return impl->paint.get<FillTranslateAnchor>(klass);
}
void FillLayer::setFillTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) {
if (value == getFillTranslateAnchor(klass))
return;
- impl->paint.fillTranslateAnchor.set(value, klass);
+ impl->paint.set<FillTranslateAnchor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -157,13 +160,13 @@ PropertyValue<std::string> FillLayer::getDefaultFillPattern() {
}
PropertyValue<std::string> FillLayer::getFillPattern(const optional<std::string>& klass) const {
- return impl->paint.fillPattern.get(klass);
+ return impl->paint.get<FillPattern>(klass);
}
void FillLayer::setFillPattern(PropertyValue<std::string> value, const optional<std::string>& klass) {
if (value == getFillPattern(klass))
return;
- impl->paint.fillPattern.set(value, klass);
+ impl->paint.set<FillPattern>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
diff --git a/src/mbgl/style/layers/fill_layer_impl.cpp b/src/mbgl/style/layers/fill_layer_impl.cpp
index fc439f1cd1..51636820f0 100644
--- a/src/mbgl/style/layers/fill_layer_impl.cpp
+++ b/src/mbgl/style/layers/fill_layer_impl.cpp
@@ -12,39 +12,38 @@ void FillLayer::Impl::cascade(const CascadeParameters& parameters) {
paint.cascade(parameters);
}
-bool FillLayer::Impl::recalculate(const CalculationParameters& parameters) {
- bool hasTransitions = paint.recalculate(parameters);
+bool FillLayer::Impl::evaluate(const PropertyEvaluationParameters& parameters) {
+ paint.evaluate(parameters);
passes = RenderPass::None;
- if (paint.fillAntialias) {
+ if (paint.evaluated.get<FillAntialias>()) {
passes |= RenderPass::Translucent;
}
- if (!paint.fillPattern.value.from.empty() || (paint.fillColor.value.a * paint.fillOpacity) < 1.0f) {
+ if (!paint.evaluated.get<FillPattern>().from.empty() || (paint.evaluated.get<FillColor>().a * paint.evaluated.get<FillOpacity>()) < 1.0f) {
passes |= RenderPass::Translucent;
} else {
passes |= RenderPass::Opaque;
}
- return hasTransitions;
+ return paint.hasTransition();
}
-std::unique_ptr<Bucket> FillLayer::Impl::createBucket(BucketParameters& parameters) const {
+std::unique_ptr<Bucket> FillLayer::Impl::createBucket(BucketParameters& parameters, const GeometryTileLayer& layer) const {
auto bucket = std::make_unique<FillBucket>();
- auto& name = bucketName();
- parameters.eachFilteredFeature(filter, [&] (const auto& feature, std::size_t index, const std::string& layerName) {
+ parameters.eachFilteredFeature(filter, layer, [&] (const auto& feature, std::size_t index, const std::string& layerName) {
auto geometries = feature.getGeometries();
bucket->addGeometry(geometries);
- parameters.featureIndex.insert(geometries, index, layerName, name);
+ parameters.featureIndex.insert(geometries, index, layerName, id);
});
return std::move(bucket);
}
float FillLayer::Impl::getQueryRadius() const {
- const std::array<float, 2>& translate = paint.fillTranslate;
+ const std::array<float, 2>& translate = paint.evaluated.get<FillTranslate>();
return util::length(translate[0], translate[1]);
}
@@ -55,7 +54,7 @@ bool FillLayer::Impl::queryIntersectsGeometry(
const float pixelsToTileUnits) const {
auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
- queryGeometry, paint.fillTranslate, paint.fillTranslateAnchor, bearing, pixelsToTileUnits);
+ queryGeometry, paint.evaluated.get<FillTranslate>(), paint.evaluated.get<FillTranslateAnchor>(), bearing, pixelsToTileUnits);
return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), geometry);
}
diff --git a/src/mbgl/style/layers/fill_layer_impl.hpp b/src/mbgl/style/layers/fill_layer_impl.hpp
index 54cfb80c86..28e2fa7edc 100644
--- a/src/mbgl/style/layers/fill_layer_impl.hpp
+++ b/src/mbgl/style/layers/fill_layer_impl.hpp
@@ -11,11 +11,12 @@ class FillLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
- bool recalculate(const CalculationParameters&) override;
+ bool evaluate(const PropertyEvaluationParameters&) override;
- std::unique_ptr<Bucket> createBucket(BucketParameters&) const override;
+ std::unique_ptr<Bucket> createBucket(BucketParameters&, const GeometryTileLayer&) const override;
float getQueryRadius() const override;
bool queryIntersectsGeometry(
diff --git a/src/mbgl/style/layers/fill_layer_properties.cpp b/src/mbgl/style/layers/fill_layer_properties.cpp
index 9a55cbc145..b07a083950 100644
--- a/src/mbgl/style/layers/fill_layer_properties.cpp
+++ b/src/mbgl/style/layers/fill_layer_properties.cpp
@@ -5,29 +5,5 @@
namespace mbgl {
namespace style {
-void FillPaintProperties::cascade(const CascadeParameters& parameters) {
- fillAntialias.cascade(parameters);
- fillOpacity.cascade(parameters);
- fillColor.cascade(parameters);
- fillOutlineColor.cascade(parameters);
- fillTranslate.cascade(parameters);
- fillTranslateAnchor.cascade(parameters);
- fillPattern.cascade(parameters);
-}
-
-bool FillPaintProperties::recalculate(const CalculationParameters& parameters) {
- bool hasTransitions = false;
-
- hasTransitions |= fillAntialias.calculate(parameters);
- hasTransitions |= fillOpacity.calculate(parameters);
- hasTransitions |= fillColor.calculate(parameters);
- hasTransitions |= fillOutlineColor.calculate(parameters);
- hasTransitions |= fillTranslate.calculate(parameters);
- hasTransitions |= fillTranslateAnchor.calculate(parameters);
- hasTransitions |= fillPattern.calculate(parameters);
-
- return hasTransitions;
-}
-
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_layer_properties.hpp b/src/mbgl/style/layers/fill_layer_properties.hpp
index d12eb8d6f4..b2d926c31e 100644
--- a/src/mbgl/style/layers/fill_layer_properties.hpp
+++ b/src/mbgl/style/layers/fill_layer_properties.hpp
@@ -9,22 +9,43 @@
namespace mbgl {
namespace style {
-class CascadeParameters;
-class CalculationParameters;
-
-class FillPaintProperties {
-public:
- void cascade(const CascadeParameters&);
- bool recalculate(const CalculationParameters&);
-
- PaintProperty<bool> fillAntialias { true };
- PaintProperty<float> fillOpacity { 1 };
- PaintProperty<Color> fillColor { Color::black() };
- PaintProperty<Color> fillOutlineColor { {} };
- PaintProperty<std::array<float, 2>> fillTranslate { {{ 0, 0 }} };
- PaintProperty<TranslateAnchorType> fillTranslateAnchor { TranslateAnchorType::Map };
- PaintProperty<std::string, CrossFadedPropertyEvaluator> fillPattern { "" };
+struct FillAntialias : PaintProperty<bool> {
+ static bool defaultValue() { return true; }
};
+struct FillOpacity : PaintProperty<float> {
+ static float defaultValue() { return 1; }
+};
+
+struct FillColor : PaintProperty<Color> {
+ static Color defaultValue() { return Color::black(); }
+};
+
+struct FillOutlineColor : PaintProperty<Color> {
+ static Color defaultValue() { return {}; }
+};
+
+struct FillTranslate : PaintProperty<std::array<float, 2>> {
+ static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+};
+
+struct FillTranslateAnchor : PaintProperty<TranslateAnchorType> {
+ static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; }
+};
+
+struct FillPattern : CrossFadedPaintProperty<std::string> {
+ static std::string defaultValue() { return ""; }
+};
+
+class FillPaintProperties : public PaintProperties<
+ FillAntialias,
+ FillOpacity,
+ FillColor,
+ FillOutlineColor,
+ FillTranslate,
+ FillTranslateAnchor,
+ FillPattern
+> {};
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs
index c2cbc56a09..e730e3a29b 100644
--- a/src/mbgl/style/layers/layer.cpp.ejs
+++ b/src/mbgl/style/layers/layer.cpp.ejs
@@ -5,8 +5,9 @@
-%>
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
-#include <mbgl/style/layers/<%- type %>_layer.hpp>
-#include <mbgl/style/layers/<%- type %>_layer_impl.hpp>
+#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp>
+#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -40,11 +41,19 @@ std::unique_ptr<Layer> <%- camelize(type) %>Layer::Impl::clone() const {
std::unique_ptr<Layer> <%- camelize(type) %>Layer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<<%- camelize(type) %>Layer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = <%- camelize(type) %>PaintProperties();
return std::move(result);
}
+<% if (layoutProperties.length) { -%>
+void <%- camelize(type) %>Layer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>& writer) const {
+ conversion::stringify(writer, layout);
+}
+<% } else { -%>
+void <%- camelize(type) %>Layer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+<% } -%>
+
<% if (type !== 'background') { -%>
// Source
@@ -78,17 +87,17 @@ const Filter& <%- camelize(type) %>Layer::getFilter() const {
<% for (const property of layoutProperties) { -%>
PropertyValue<<%- propertyType(property) %>> <%- camelize(type) %>Layer::getDefault<%- camelize(property.name) %>() {
- return { <%- defaultValue(property) %> };
+ return <%- camelize(property.name) %>::defaultValue();
}
PropertyValue<<%- propertyType(property) %>> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>() const {
- return impl->layout.<%- camelizeWithLeadingLowercase(property.name) %>.get();
+ return impl->layout.unevaluated.get<<%- camelize(property.name) %>>();
}
void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>> value) {
if (value == get<%- camelize(property.name) %>())
return;
- impl->layout.<%- camelizeWithLeadingLowercase(property.name) %>.set(value);
+ impl->layout.unevaluated.get<<%- camelize(property.name) %>>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "<%- property.name %>");
}
<% } -%>
@@ -100,13 +109,13 @@ PropertyValue<<%- propertyType(property) %>> <%- camelize(type) %>Layer::getDefa
}
PropertyValue<<%- propertyType(property) %>> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>(const optional<std::string>& klass) const {
- return impl->paint.<%- camelizeWithLeadingLowercase(property.name) %>.get(klass);
+ return impl->paint.get<<%- camelize(property.name) %>>(klass);
}
void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>> value, const optional<std::string>& klass) {
if (value == get<%- camelize(property.name) %>(klass))
return;
- impl->paint.<%- camelizeWithLeadingLowercase(property.name) %>.set(value, klass);
+ impl->paint.set<<%- camelize(property.name) %>>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
<% } -%>
diff --git a/src/mbgl/style/layers/layer_properties.cpp.ejs b/src/mbgl/style/layers/layer_properties.cpp.ejs
index b781a4a9d9..e5523e5439 100644
--- a/src/mbgl/style/layers/layer_properties.cpp.ejs
+++ b/src/mbgl/style/layers/layer_properties.cpp.ejs
@@ -5,34 +5,10 @@
-%>
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
-#include <mbgl/style/layers/<%- type %>_layer_properties.hpp>
+#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer_properties.hpp>
namespace mbgl {
namespace style {
-<% if (layoutProperties.length) { -%>
-void <%- camelize(type) %>LayoutProperties::recalculate(const CalculationParameters& parameters) {
-<% for (const property of layoutProperties) { -%>
- <%- camelizeWithLeadingLowercase(property.name) %>.calculate(parameters);
-<% } -%>
-}
-
-<% } -%>
-void <%- camelize(type) %>PaintProperties::cascade(const CascadeParameters& parameters) {
-<% for (const property of paintProperties) { -%>
- <%- camelizeWithLeadingLowercase(property.name) %>.cascade(parameters);
-<% } -%>
-}
-
-bool <%- camelize(type) %>PaintProperties::recalculate(const CalculationParameters& parameters) {
- bool hasTransitions = false;
-
-<% for (const property of paintProperties) { -%>
- hasTransitions |= <%- camelizeWithLeadingLowercase(property.name) %>.calculate(parameters);
-<% } -%>
-
- return hasTransitions;
-}
-
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/layer_properties.hpp.ejs b/src/mbgl/style/layers/layer_properties.hpp.ejs
index 0c91ecba8c..d18ad44efd 100644
--- a/src/mbgl/style/layers/layer_properties.hpp.ejs
+++ b/src/mbgl/style/layers/layer_properties.hpp.ejs
@@ -14,33 +14,36 @@
namespace mbgl {
namespace style {
-class CascadeParameters;
-class CalculationParameters;
-
-<% if (layoutProperties.length) { -%>
-class <%- camelize(type) %>LayoutProperties {
-public:
- void recalculate(const CalculationParameters&);
-
<% for (const property of layoutProperties) { -%>
- LayoutProperty<<%- propertyType(property) %>> <%- camelizeWithLeadingLowercase(property.name) %> { <%- defaultValue(property) %> };
+struct <%- camelize(property.name) %> : LayoutProperty<<%- propertyType(property) %>> {
+ static constexpr const char * key = "<%- property.name %>";
+ static <%- propertyType(property) %> defaultValue() { return <%- defaultValue(property) %>; }
+};
+
<% } -%>
+<% for (const property of paintProperties) { -%>
+struct <%- camelize(property.name) %> : <%
+if (/-pattern$/.test(property.name) || property.name === 'line-dasharray') {
+%>CrossFaded<% } -%>PaintProperty<<%- propertyType(property) %>> {
+ static <%- propertyType(property) %> defaultValue() { return <%- defaultValue(property) %>; }
};
<% } -%>
-class <%- camelize(type) %>PaintProperties {
-public:
- void cascade(const CascadeParameters&);
- bool recalculate(const CalculationParameters&);
+<% if (layoutProperties.length) { -%>
+class <%- camelize(type) %>LayoutProperties : public LayoutProperties<
+<% for (const property of layoutProperties.slice(0, -1)) { -%>
+ <%- camelize(property.name) %>,
+<% } -%>
+ <%- camelize(layoutProperties.slice(-1)[0].name) %>
+> {};
-<% for (const property of paintProperties) { -%>
-<% if (/-pattern$/.test(property.name) || property.name === 'line-dasharray') { -%>
- PaintProperty<<%- propertyType(property) %>, CrossFadedPropertyEvaluator> <%- camelizeWithLeadingLowercase(property.name) %> { <%- defaultValue(property) %> };
-<% } else { -%>
- PaintProperty<<%- propertyType(property) %>> <%- camelizeWithLeadingLowercase(property.name) %> { <%- defaultValue(property) %> };
<% } -%>
+class <%- camelize(type) %>PaintProperties : public PaintProperties<
+<% for (const property of paintProperties.slice(0, -1)) { -%>
+ <%- camelize(property.name) %>,
<% } -%>
-};
+ <%- camelize(paintProperties.slice(-1)[0].name) %>
+> {};
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp
index 49ecf63c18..7f6c148cd1 100644
--- a/src/mbgl/style/layers/line_layer.cpp
+++ b/src/mbgl/style/layers/line_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -27,11 +28,14 @@ std::unique_ptr<Layer> LineLayer::Impl::clone() const {
std::unique_ptr<Layer> LineLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<LineLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = LinePaintProperties();
return std::move(result);
}
+void LineLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>& writer) const {
+ conversion::stringify(writer, layout);
+}
+
// Source
const std::string& LineLayer::getSourceID() const {
@@ -60,59 +64,59 @@ const Filter& LineLayer::getFilter() const {
// Layout properties
PropertyValue<LineCapType> LineLayer::getDefaultLineCap() {
- return { LineCapType::Butt };
+ return LineCap::defaultValue();
}
PropertyValue<LineCapType> LineLayer::getLineCap() const {
- return impl->layout.lineCap.get();
+ return impl->layout.unevaluated.get<LineCap>();
}
void LineLayer::setLineCap(PropertyValue<LineCapType> value) {
if (value == getLineCap())
return;
- impl->layout.lineCap.set(value);
+ impl->layout.unevaluated.get<LineCap>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "line-cap");
}
PropertyValue<LineJoinType> LineLayer::getDefaultLineJoin() {
- return { LineJoinType::Miter };
+ return LineJoin::defaultValue();
}
PropertyValue<LineJoinType> LineLayer::getLineJoin() const {
- return impl->layout.lineJoin.get();
+ return impl->layout.unevaluated.get<LineJoin>();
}
void LineLayer::setLineJoin(PropertyValue<LineJoinType> value) {
if (value == getLineJoin())
return;
- impl->layout.lineJoin.set(value);
+ impl->layout.unevaluated.get<LineJoin>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "line-join");
}
PropertyValue<float> LineLayer::getDefaultLineMiterLimit() {
- return { 2 };
+ return LineMiterLimit::defaultValue();
}
PropertyValue<float> LineLayer::getLineMiterLimit() const {
- return impl->layout.lineMiterLimit.get();
+ return impl->layout.unevaluated.get<LineMiterLimit>();
}
void LineLayer::setLineMiterLimit(PropertyValue<float> value) {
if (value == getLineMiterLimit())
return;
- impl->layout.lineMiterLimit.set(value);
+ impl->layout.unevaluated.get<LineMiterLimit>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "line-miter-limit");
}
PropertyValue<float> LineLayer::getDefaultLineRoundLimit() {
- return { 1 };
+ return LineRoundLimit::defaultValue();
}
PropertyValue<float> LineLayer::getLineRoundLimit() const {
- return impl->layout.lineRoundLimit.get();
+ return impl->layout.unevaluated.get<LineRoundLimit>();
}
void LineLayer::setLineRoundLimit(PropertyValue<float> value) {
if (value == getLineRoundLimit())
return;
- impl->layout.lineRoundLimit.set(value);
+ impl->layout.unevaluated.get<LineRoundLimit>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "line-round-limit");
}
@@ -123,13 +127,13 @@ PropertyValue<float> LineLayer::getDefaultLineOpacity() {
}
PropertyValue<float> LineLayer::getLineOpacity(const optional<std::string>& klass) const {
- return impl->paint.lineOpacity.get(klass);
+ return impl->paint.get<LineOpacity>(klass);
}
void LineLayer::setLineOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getLineOpacity(klass))
return;
- impl->paint.lineOpacity.set(value, klass);
+ impl->paint.set<LineOpacity>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -138,13 +142,13 @@ PropertyValue<Color> LineLayer::getDefaultLineColor() {
}
PropertyValue<Color> LineLayer::getLineColor(const optional<std::string>& klass) const {
- return impl->paint.lineColor.get(klass);
+ return impl->paint.get<LineColor>(klass);
}
void LineLayer::setLineColor(PropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getLineColor(klass))
return;
- impl->paint.lineColor.set(value, klass);
+ impl->paint.set<LineColor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -153,13 +157,13 @@ PropertyValue<std::array<float, 2>> LineLayer::getDefaultLineTranslate() {
}
PropertyValue<std::array<float, 2>> LineLayer::getLineTranslate(const optional<std::string>& klass) const {
- return impl->paint.lineTranslate.get(klass);
+ return impl->paint.get<LineTranslate>(klass);
}
void LineLayer::setLineTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) {
if (value == getLineTranslate(klass))
return;
- impl->paint.lineTranslate.set(value, klass);
+ impl->paint.set<LineTranslate>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -168,13 +172,13 @@ PropertyValue<TranslateAnchorType> LineLayer::getDefaultLineTranslateAnchor() {
}
PropertyValue<TranslateAnchorType> LineLayer::getLineTranslateAnchor(const optional<std::string>& klass) const {
- return impl->paint.lineTranslateAnchor.get(klass);
+ return impl->paint.get<LineTranslateAnchor>(klass);
}
void LineLayer::setLineTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) {
if (value == getLineTranslateAnchor(klass))
return;
- impl->paint.lineTranslateAnchor.set(value, klass);
+ impl->paint.set<LineTranslateAnchor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -183,13 +187,13 @@ PropertyValue<float> LineLayer::getDefaultLineWidth() {
}
PropertyValue<float> LineLayer::getLineWidth(const optional<std::string>& klass) const {
- return impl->paint.lineWidth.get(klass);
+ return impl->paint.get<LineWidth>(klass);
}
void LineLayer::setLineWidth(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getLineWidth(klass))
return;
- impl->paint.lineWidth.set(value, klass);
+ impl->paint.set<LineWidth>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -198,13 +202,13 @@ PropertyValue<float> LineLayer::getDefaultLineGapWidth() {
}
PropertyValue<float> LineLayer::getLineGapWidth(const optional<std::string>& klass) const {
- return impl->paint.lineGapWidth.get(klass);
+ return impl->paint.get<LineGapWidth>(klass);
}
void LineLayer::setLineGapWidth(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getLineGapWidth(klass))
return;
- impl->paint.lineGapWidth.set(value, klass);
+ impl->paint.set<LineGapWidth>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -213,13 +217,13 @@ PropertyValue<float> LineLayer::getDefaultLineOffset() {
}
PropertyValue<float> LineLayer::getLineOffset(const optional<std::string>& klass) const {
- return impl->paint.lineOffset.get(klass);
+ return impl->paint.get<LineOffset>(klass);
}
void LineLayer::setLineOffset(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getLineOffset(klass))
return;
- impl->paint.lineOffset.set(value, klass);
+ impl->paint.set<LineOffset>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -228,13 +232,13 @@ PropertyValue<float> LineLayer::getDefaultLineBlur() {
}
PropertyValue<float> LineLayer::getLineBlur(const optional<std::string>& klass) const {
- return impl->paint.lineBlur.get(klass);
+ return impl->paint.get<LineBlur>(klass);
}
void LineLayer::setLineBlur(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getLineBlur(klass))
return;
- impl->paint.lineBlur.set(value, klass);
+ impl->paint.set<LineBlur>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -243,13 +247,13 @@ PropertyValue<std::vector<float>> LineLayer::getDefaultLineDasharray() {
}
PropertyValue<std::vector<float>> LineLayer::getLineDasharray(const optional<std::string>& klass) const {
- return impl->paint.lineDasharray.get(klass);
+ return impl->paint.get<LineDasharray>(klass);
}
void LineLayer::setLineDasharray(PropertyValue<std::vector<float>> value, const optional<std::string>& klass) {
if (value == getLineDasharray(klass))
return;
- impl->paint.lineDasharray.set(value, klass);
+ impl->paint.set<LineDasharray>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -258,13 +262,13 @@ PropertyValue<std::string> LineLayer::getDefaultLinePattern() {
}
PropertyValue<std::string> LineLayer::getLinePattern(const optional<std::string>& klass) const {
- return impl->paint.linePattern.get(klass);
+ return impl->paint.get<LinePattern>(klass);
}
void LineLayer::setLinePattern(PropertyValue<std::string> value, const optional<std::string>& klass) {
if (value == getLinePattern(klass))
return;
- impl->paint.linePattern.set(value, klass);
+ impl->paint.set<LinePattern>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
diff --git a/src/mbgl/style/layers/line_layer_impl.cpp b/src/mbgl/style/layers/line_layer_impl.cpp
index c116af5fc2..477579a43c 100644
--- a/src/mbgl/style/layers/line_layer_impl.cpp
+++ b/src/mbgl/style/layers/line_layer_impl.cpp
@@ -12,42 +12,39 @@ void LineLayer::Impl::cascade(const CascadeParameters& parameters) {
paint.cascade(parameters);
}
-bool LineLayer::Impl::recalculate(const CalculationParameters& parameters) {
+bool LineLayer::Impl::evaluate(const PropertyEvaluationParameters& parameters) {
// for scaling dasharrays
- CalculationParameters dashArrayParams = parameters;
+ PropertyEvaluationParameters dashArrayParams = parameters;
dashArrayParams.z = std::floor(dashArrayParams.z);
- paint.lineWidth.calculate(dashArrayParams);
- dashLineWidth = paint.lineWidth;
+ dashLineWidth = paint.evaluate<LineWidth>(dashArrayParams);
- bool hasTransitions = paint.recalculate(parameters);
+ paint.evaluate(parameters);
- passes = (paint.lineOpacity > 0 && paint.lineColor.value.a > 0 && paint.lineWidth > 0)
+ passes = (paint.evaluated.get<LineOpacity>() > 0 && paint.evaluated.get<LineColor>().a > 0 && paint.evaluated.get<LineWidth>() > 0)
? RenderPass::Translucent : RenderPass::None;
- return hasTransitions;
+ return paint.hasTransition();
}
-std::unique_ptr<Bucket> LineLayer::Impl::createBucket(BucketParameters& parameters) const {
+std::unique_ptr<Bucket> LineLayer::Impl::createBucket(BucketParameters& parameters, const GeometryTileLayer& layer) const {
auto bucket = std::make_unique<LineBucket>(parameters.tileID.overscaleFactor());
- bucket->layout = layout;
- bucket->layout.recalculate(CalculationParameters(parameters.tileID.overscaledZ));
+ bucket->layout = layout.evaluate(PropertyEvaluationParameters(parameters.tileID.overscaledZ));
- auto& name = bucketName();
- parameters.eachFilteredFeature(filter, [&] (const auto& feature, std::size_t index, const std::string& layerName) {
+ parameters.eachFilteredFeature(filter, layer, [&] (const auto& feature, std::size_t index, const std::string& layerName) {
auto geometries = feature.getGeometries();
bucket->addGeometry(geometries);
- parameters.featureIndex.insert(geometries, index, layerName, name);
+ parameters.featureIndex.insert(geometries, index, layerName, id);
});
return std::move(bucket);
}
float LineLayer::Impl::getLineWidth() const {
- if (paint.lineGapWidth > 0) {
- return paint.lineGapWidth + 2 * paint.lineWidth;
+ if (paint.evaluated.get<LineGapWidth>() > 0) {
+ return paint.evaluated.get<LineGapWidth>() + 2 * paint.evaluated.get<LineWidth>();
} else {
- return paint.lineWidth;
+ return paint.evaluated.get<LineWidth>();
}
}
@@ -82,8 +79,8 @@ optional<GeometryCollection> offsetLine(const GeometryCollection& rings, const d
}
float LineLayer::Impl::getQueryRadius() const {
- const std::array<float, 2>& translate = paint.lineTranslate;
- return getLineWidth() / 2.0 + std::abs(paint.lineOffset) + util::length(translate[0], translate[1]);
+ const std::array<float, 2>& translate = paint.evaluated.get<LineTranslate>();
+ return getLineWidth() / 2.0 + std::abs(paint.evaluated.get<LineOffset>()) + util::length(translate[0], translate[1]);
}
bool LineLayer::Impl::queryIntersectsGeometry(
@@ -95,8 +92,8 @@ bool LineLayer::Impl::queryIntersectsGeometry(
const float halfWidth = getLineWidth() / 2.0 * pixelsToTileUnits;
auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
- queryGeometry, paint.lineTranslate, paint.lineTranslateAnchor, bearing, pixelsToTileUnits);
- auto offsetGeometry = offsetLine(geometry, paint.lineOffset * pixelsToTileUnits);
+ queryGeometry, paint.evaluated.get<LineTranslate>(), paint.evaluated.get<LineTranslateAnchor>(), bearing, pixelsToTileUnits);
+ auto offsetGeometry = offsetLine(geometry, paint.evaluated.get<LineOffset>() * pixelsToTileUnits);
return util::polygonIntersectsBufferedMultiLine(
translatedQueryGeometry.value_or(queryGeometry),
diff --git a/src/mbgl/style/layers/line_layer_impl.hpp b/src/mbgl/style/layers/line_layer_impl.hpp
index c6b4be3bec..1955c019af 100644
--- a/src/mbgl/style/layers/line_layer_impl.hpp
+++ b/src/mbgl/style/layers/line_layer_impl.hpp
@@ -11,11 +11,12 @@ class LineLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
- bool recalculate(const CalculationParameters&) override;
+ bool evaluate(const PropertyEvaluationParameters&) override;
- std::unique_ptr<Bucket> createBucket(BucketParameters&) const override;
+ std::unique_ptr<Bucket> createBucket(BucketParameters&, const GeometryTileLayer&) const override;
float getQueryRadius() const override;
bool queryIntersectsGeometry(
diff --git a/src/mbgl/style/layers/line_layer_properties.cpp b/src/mbgl/style/layers/line_layer_properties.cpp
index 2d6092745e..174239bcc8 100644
--- a/src/mbgl/style/layers/line_layer_properties.cpp
+++ b/src/mbgl/style/layers/line_layer_properties.cpp
@@ -5,42 +5,5 @@
namespace mbgl {
namespace style {
-void LineLayoutProperties::recalculate(const CalculationParameters& parameters) {
- lineCap.calculate(parameters);
- lineJoin.calculate(parameters);
- lineMiterLimit.calculate(parameters);
- lineRoundLimit.calculate(parameters);
-}
-
-void LinePaintProperties::cascade(const CascadeParameters& parameters) {
- lineOpacity.cascade(parameters);
- lineColor.cascade(parameters);
- lineTranslate.cascade(parameters);
- lineTranslateAnchor.cascade(parameters);
- lineWidth.cascade(parameters);
- lineGapWidth.cascade(parameters);
- lineOffset.cascade(parameters);
- lineBlur.cascade(parameters);
- lineDasharray.cascade(parameters);
- linePattern.cascade(parameters);
-}
-
-bool LinePaintProperties::recalculate(const CalculationParameters& parameters) {
- bool hasTransitions = false;
-
- hasTransitions |= lineOpacity.calculate(parameters);
- hasTransitions |= lineColor.calculate(parameters);
- hasTransitions |= lineTranslate.calculate(parameters);
- hasTransitions |= lineTranslateAnchor.calculate(parameters);
- hasTransitions |= lineWidth.calculate(parameters);
- hasTransitions |= lineGapWidth.calculate(parameters);
- hasTransitions |= lineOffset.calculate(parameters);
- hasTransitions |= lineBlur.calculate(parameters);
- hasTransitions |= lineDasharray.calculate(parameters);
- hasTransitions |= linePattern.calculate(parameters);
-
- return hasTransitions;
-}
-
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/line_layer_properties.hpp b/src/mbgl/style/layers/line_layer_properties.hpp
index b73e3f2ef2..2ea7f6b125 100644
--- a/src/mbgl/style/layers/line_layer_properties.hpp
+++ b/src/mbgl/style/layers/line_layer_properties.hpp
@@ -9,35 +9,85 @@
namespace mbgl {
namespace style {
-class CascadeParameters;
-class CalculationParameters;
-
-class LineLayoutProperties {
-public:
- void recalculate(const CalculationParameters&);
-
- LayoutProperty<LineCapType> lineCap { LineCapType::Butt };
- LayoutProperty<LineJoinType> lineJoin { LineJoinType::Miter };
- LayoutProperty<float> lineMiterLimit { 2 };
- LayoutProperty<float> lineRoundLimit { 1 };
-};
-
-class LinePaintProperties {
-public:
- void cascade(const CascadeParameters&);
- bool recalculate(const CalculationParameters&);
-
- PaintProperty<float> lineOpacity { 1 };
- PaintProperty<Color> lineColor { Color::black() };
- PaintProperty<std::array<float, 2>> lineTranslate { {{ 0, 0 }} };
- PaintProperty<TranslateAnchorType> lineTranslateAnchor { TranslateAnchorType::Map };
- PaintProperty<float> lineWidth { 1 };
- PaintProperty<float> lineGapWidth { 0 };
- PaintProperty<float> lineOffset { 0 };
- PaintProperty<float> lineBlur { 0 };
- PaintProperty<std::vector<float>, CrossFadedPropertyEvaluator> lineDasharray { { } };
- PaintProperty<std::string, CrossFadedPropertyEvaluator> linePattern { "" };
+struct LineCap : LayoutProperty<LineCapType> {
+ static constexpr const char * key = "line-cap";
+ static LineCapType defaultValue() { return LineCapType::Butt; }
};
+struct LineJoin : LayoutProperty<LineJoinType> {
+ static constexpr const char * key = "line-join";
+ static LineJoinType defaultValue() { return LineJoinType::Miter; }
+};
+
+struct LineMiterLimit : LayoutProperty<float> {
+ static constexpr const char * key = "line-miter-limit";
+ static float defaultValue() { return 2; }
+};
+
+struct LineRoundLimit : LayoutProperty<float> {
+ static constexpr const char * key = "line-round-limit";
+ static float defaultValue() { return 1; }
+};
+
+struct LineOpacity : PaintProperty<float> {
+ static float defaultValue() { return 1; }
+};
+
+struct LineColor : PaintProperty<Color> {
+ static Color defaultValue() { return Color::black(); }
+};
+
+struct LineTranslate : PaintProperty<std::array<float, 2>> {
+ static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+};
+
+struct LineTranslateAnchor : PaintProperty<TranslateAnchorType> {
+ static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; }
+};
+
+struct LineWidth : PaintProperty<float> {
+ static float defaultValue() { return 1; }
+};
+
+struct LineGapWidth : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct LineOffset : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct LineBlur : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct LineDasharray : CrossFadedPaintProperty<std::vector<float>> {
+ static std::vector<float> defaultValue() { return { }; }
+};
+
+struct LinePattern : CrossFadedPaintProperty<std::string> {
+ static std::string defaultValue() { return ""; }
+};
+
+class LineLayoutProperties : public LayoutProperties<
+ LineCap,
+ LineJoin,
+ LineMiterLimit,
+ LineRoundLimit
+> {};
+
+class LinePaintProperties : public PaintProperties<
+ LineOpacity,
+ LineColor,
+ LineTranslate,
+ LineTranslateAnchor,
+ LineWidth,
+ LineGapWidth,
+ LineOffset,
+ LineBlur,
+ LineDasharray,
+ LinePattern
+> {};
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp
index 238bfef6e4..0fda27f0dc 100644
--- a/src/mbgl/style/layers/raster_layer.cpp
+++ b/src/mbgl/style/layers/raster_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/raster_layer.hpp>
#include <mbgl/style/layers/raster_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -27,11 +28,13 @@ std::unique_ptr<Layer> RasterLayer::Impl::clone() const {
std::unique_ptr<Layer> RasterLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<RasterLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = RasterPaintProperties();
return std::move(result);
}
+void RasterLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+
// Source
const std::string& RasterLayer::getSourceID() const {
@@ -49,13 +52,13 @@ PropertyValue<float> RasterLayer::getDefaultRasterOpacity() {
}
PropertyValue<float> RasterLayer::getRasterOpacity(const optional<std::string>& klass) const {
- return impl->paint.rasterOpacity.get(klass);
+ return impl->paint.get<RasterOpacity>(klass);
}
void RasterLayer::setRasterOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getRasterOpacity(klass))
return;
- impl->paint.rasterOpacity.set(value, klass);
+ impl->paint.set<RasterOpacity>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -64,13 +67,13 @@ PropertyValue<float> RasterLayer::getDefaultRasterHueRotate() {
}
PropertyValue<float> RasterLayer::getRasterHueRotate(const optional<std::string>& klass) const {
- return impl->paint.rasterHueRotate.get(klass);
+ return impl->paint.get<RasterHueRotate>(klass);
}
void RasterLayer::setRasterHueRotate(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getRasterHueRotate(klass))
return;
- impl->paint.rasterHueRotate.set(value, klass);
+ impl->paint.set<RasterHueRotate>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -79,13 +82,13 @@ PropertyValue<float> RasterLayer::getDefaultRasterBrightnessMin() {
}
PropertyValue<float> RasterLayer::getRasterBrightnessMin(const optional<std::string>& klass) const {
- return impl->paint.rasterBrightnessMin.get(klass);
+ return impl->paint.get<RasterBrightnessMin>(klass);
}
void RasterLayer::setRasterBrightnessMin(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getRasterBrightnessMin(klass))
return;
- impl->paint.rasterBrightnessMin.set(value, klass);
+ impl->paint.set<RasterBrightnessMin>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -94,13 +97,13 @@ PropertyValue<float> RasterLayer::getDefaultRasterBrightnessMax() {
}
PropertyValue<float> RasterLayer::getRasterBrightnessMax(const optional<std::string>& klass) const {
- return impl->paint.rasterBrightnessMax.get(klass);
+ return impl->paint.get<RasterBrightnessMax>(klass);
}
void RasterLayer::setRasterBrightnessMax(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getRasterBrightnessMax(klass))
return;
- impl->paint.rasterBrightnessMax.set(value, klass);
+ impl->paint.set<RasterBrightnessMax>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -109,13 +112,13 @@ PropertyValue<float> RasterLayer::getDefaultRasterSaturation() {
}
PropertyValue<float> RasterLayer::getRasterSaturation(const optional<std::string>& klass) const {
- return impl->paint.rasterSaturation.get(klass);
+ return impl->paint.get<RasterSaturation>(klass);
}
void RasterLayer::setRasterSaturation(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getRasterSaturation(klass))
return;
- impl->paint.rasterSaturation.set(value, klass);
+ impl->paint.set<RasterSaturation>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -124,13 +127,13 @@ PropertyValue<float> RasterLayer::getDefaultRasterContrast() {
}
PropertyValue<float> RasterLayer::getRasterContrast(const optional<std::string>& klass) const {
- return impl->paint.rasterContrast.get(klass);
+ return impl->paint.get<RasterContrast>(klass);
}
void RasterLayer::setRasterContrast(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getRasterContrast(klass))
return;
- impl->paint.rasterContrast.set(value, klass);
+ impl->paint.set<RasterContrast>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -139,13 +142,13 @@ PropertyValue<float> RasterLayer::getDefaultRasterFadeDuration() {
}
PropertyValue<float> RasterLayer::getRasterFadeDuration(const optional<std::string>& klass) const {
- return impl->paint.rasterFadeDuration.get(klass);
+ return impl->paint.get<RasterFadeDuration>(klass);
}
void RasterLayer::setRasterFadeDuration(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getRasterFadeDuration(klass))
return;
- impl->paint.rasterFadeDuration.set(value, klass);
+ impl->paint.set<RasterFadeDuration>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
diff --git a/src/mbgl/style/layers/raster_layer_impl.cpp b/src/mbgl/style/layers/raster_layer_impl.cpp
index 879bfa4559..a78614aee9 100644
--- a/src/mbgl/style/layers/raster_layer_impl.cpp
+++ b/src/mbgl/style/layers/raster_layer_impl.cpp
@@ -8,15 +8,15 @@ void RasterLayer::Impl::cascade(const CascadeParameters& parameters) {
paint.cascade(parameters);
}
-bool RasterLayer::Impl::recalculate(const CalculationParameters& parameters) {
- bool hasTransitions = paint.recalculate(parameters);
+bool RasterLayer::Impl::evaluate(const PropertyEvaluationParameters& parameters) {
+ paint.evaluate(parameters);
- passes = paint.rasterOpacity > 0 ? RenderPass::Translucent : RenderPass::None;
+ passes = paint.evaluated.get<RasterOpacity>() > 0 ? RenderPass::Translucent : RenderPass::None;
- return hasTransitions;
+ return paint.hasTransition();
}
-std::unique_ptr<Bucket> RasterLayer::Impl::createBucket(BucketParameters&) const {
+std::unique_ptr<Bucket> RasterLayer::Impl::createBucket(BucketParameters&, const GeometryTileLayer&) const {
return nullptr;
}
diff --git a/src/mbgl/style/layers/raster_layer_impl.hpp b/src/mbgl/style/layers/raster_layer_impl.hpp
index a5b396e2ed..8e69c21ca8 100644
--- a/src/mbgl/style/layers/raster_layer_impl.hpp
+++ b/src/mbgl/style/layers/raster_layer_impl.hpp
@@ -11,11 +11,12 @@ class RasterLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
- bool recalculate(const CalculationParameters&) override;
+ bool evaluate(const PropertyEvaluationParameters&) override;
- std::unique_ptr<Bucket> createBucket(BucketParameters&) const override;
+ std::unique_ptr<Bucket> createBucket(BucketParameters&, const GeometryTileLayer&) const override;
RasterPaintProperties paint;
};
diff --git a/src/mbgl/style/layers/raster_layer_properties.cpp b/src/mbgl/style/layers/raster_layer_properties.cpp
index 68d9d1d35d..303719af40 100644
--- a/src/mbgl/style/layers/raster_layer_properties.cpp
+++ b/src/mbgl/style/layers/raster_layer_properties.cpp
@@ -5,29 +5,5 @@
namespace mbgl {
namespace style {
-void RasterPaintProperties::cascade(const CascadeParameters& parameters) {
- rasterOpacity.cascade(parameters);
- rasterHueRotate.cascade(parameters);
- rasterBrightnessMin.cascade(parameters);
- rasterBrightnessMax.cascade(parameters);
- rasterSaturation.cascade(parameters);
- rasterContrast.cascade(parameters);
- rasterFadeDuration.cascade(parameters);
-}
-
-bool RasterPaintProperties::recalculate(const CalculationParameters& parameters) {
- bool hasTransitions = false;
-
- hasTransitions |= rasterOpacity.calculate(parameters);
- hasTransitions |= rasterHueRotate.calculate(parameters);
- hasTransitions |= rasterBrightnessMin.calculate(parameters);
- hasTransitions |= rasterBrightnessMax.calculate(parameters);
- hasTransitions |= rasterSaturation.calculate(parameters);
- hasTransitions |= rasterContrast.calculate(parameters);
- hasTransitions |= rasterFadeDuration.calculate(parameters);
-
- return hasTransitions;
-}
-
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/raster_layer_properties.hpp b/src/mbgl/style/layers/raster_layer_properties.hpp
index ddfb833e12..caa6d0c58d 100644
--- a/src/mbgl/style/layers/raster_layer_properties.hpp
+++ b/src/mbgl/style/layers/raster_layer_properties.hpp
@@ -9,22 +9,43 @@
namespace mbgl {
namespace style {
-class CascadeParameters;
-class CalculationParameters;
-
-class RasterPaintProperties {
-public:
- void cascade(const CascadeParameters&);
- bool recalculate(const CalculationParameters&);
-
- PaintProperty<float> rasterOpacity { 1 };
- PaintProperty<float> rasterHueRotate { 0 };
- PaintProperty<float> rasterBrightnessMin { 0 };
- PaintProperty<float> rasterBrightnessMax { 1 };
- PaintProperty<float> rasterSaturation { 0 };
- PaintProperty<float> rasterContrast { 0 };
- PaintProperty<float> rasterFadeDuration { 300 };
+struct RasterOpacity : PaintProperty<float> {
+ static float defaultValue() { return 1; }
};
+struct RasterHueRotate : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct RasterBrightnessMin : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct RasterBrightnessMax : PaintProperty<float> {
+ static float defaultValue() { return 1; }
+};
+
+struct RasterSaturation : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct RasterContrast : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct RasterFadeDuration : PaintProperty<float> {
+ static float defaultValue() { return 300; }
+};
+
+class RasterPaintProperties : public PaintProperties<
+ RasterOpacity,
+ RasterHueRotate,
+ RasterBrightnessMin,
+ RasterBrightnessMax,
+ RasterSaturation,
+ RasterContrast,
+ RasterFadeDuration
+> {};
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index d49e8d7fe3..c9014e7ee7 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -27,11 +28,14 @@ std::unique_ptr<Layer> SymbolLayer::Impl::clone() const {
std::unique_ptr<Layer> SymbolLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<SymbolLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = SymbolPaintProperties();
return std::move(result);
}
+void SymbolLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>& writer) const {
+ conversion::stringify(writer, layout);
+}
+
// Source
const std::string& SymbolLayer::getSourceID() const {
@@ -60,479 +64,479 @@ const Filter& SymbolLayer::getFilter() const {
// Layout properties
PropertyValue<SymbolPlacementType> SymbolLayer::getDefaultSymbolPlacement() {
- return { SymbolPlacementType::Point };
+ return SymbolPlacement::defaultValue();
}
PropertyValue<SymbolPlacementType> SymbolLayer::getSymbolPlacement() const {
- return impl->layout.symbolPlacement.get();
+ return impl->layout.unevaluated.get<SymbolPlacement>();
}
void SymbolLayer::setSymbolPlacement(PropertyValue<SymbolPlacementType> value) {
if (value == getSymbolPlacement())
return;
- impl->layout.symbolPlacement.set(value);
+ impl->layout.unevaluated.get<SymbolPlacement>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "symbol-placement");
}
PropertyValue<float> SymbolLayer::getDefaultSymbolSpacing() {
- return { 250 };
+ return SymbolSpacing::defaultValue();
}
PropertyValue<float> SymbolLayer::getSymbolSpacing() const {
- return impl->layout.symbolSpacing.get();
+ return impl->layout.unevaluated.get<SymbolSpacing>();
}
void SymbolLayer::setSymbolSpacing(PropertyValue<float> value) {
if (value == getSymbolSpacing())
return;
- impl->layout.symbolSpacing.set(value);
+ impl->layout.unevaluated.get<SymbolSpacing>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "symbol-spacing");
}
PropertyValue<bool> SymbolLayer::getDefaultSymbolAvoidEdges() {
- return { false };
+ return SymbolAvoidEdges::defaultValue();
}
PropertyValue<bool> SymbolLayer::getSymbolAvoidEdges() const {
- return impl->layout.symbolAvoidEdges.get();
+ return impl->layout.unevaluated.get<SymbolAvoidEdges>();
}
void SymbolLayer::setSymbolAvoidEdges(PropertyValue<bool> value) {
if (value == getSymbolAvoidEdges())
return;
- impl->layout.symbolAvoidEdges.set(value);
+ impl->layout.unevaluated.get<SymbolAvoidEdges>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "symbol-avoid-edges");
}
PropertyValue<bool> SymbolLayer::getDefaultIconAllowOverlap() {
- return { false };
+ return IconAllowOverlap::defaultValue();
}
PropertyValue<bool> SymbolLayer::getIconAllowOverlap() const {
- return impl->layout.iconAllowOverlap.get();
+ return impl->layout.unevaluated.get<IconAllowOverlap>();
}
void SymbolLayer::setIconAllowOverlap(PropertyValue<bool> value) {
if (value == getIconAllowOverlap())
return;
- impl->layout.iconAllowOverlap.set(value);
+ impl->layout.unevaluated.get<IconAllowOverlap>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "icon-allow-overlap");
}
PropertyValue<bool> SymbolLayer::getDefaultIconIgnorePlacement() {
- return { false };
+ return IconIgnorePlacement::defaultValue();
}
PropertyValue<bool> SymbolLayer::getIconIgnorePlacement() const {
- return impl->layout.iconIgnorePlacement.get();
+ return impl->layout.unevaluated.get<IconIgnorePlacement>();
}
void SymbolLayer::setIconIgnorePlacement(PropertyValue<bool> value) {
if (value == getIconIgnorePlacement())
return;
- impl->layout.iconIgnorePlacement.set(value);
+ impl->layout.unevaluated.get<IconIgnorePlacement>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "icon-ignore-placement");
}
PropertyValue<bool> SymbolLayer::getDefaultIconOptional() {
- return { false };
+ return IconOptional::defaultValue();
}
PropertyValue<bool> SymbolLayer::getIconOptional() const {
- return impl->layout.iconOptional.get();
+ return impl->layout.unevaluated.get<IconOptional>();
}
void SymbolLayer::setIconOptional(PropertyValue<bool> value) {
if (value == getIconOptional())
return;
- impl->layout.iconOptional.set(value);
+ impl->layout.unevaluated.get<IconOptional>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "icon-optional");
}
PropertyValue<AlignmentType> SymbolLayer::getDefaultIconRotationAlignment() {
- return { AlignmentType::Auto };
+ return IconRotationAlignment::defaultValue();
}
PropertyValue<AlignmentType> SymbolLayer::getIconRotationAlignment() const {
- return impl->layout.iconRotationAlignment.get();
+ return impl->layout.unevaluated.get<IconRotationAlignment>();
}
void SymbolLayer::setIconRotationAlignment(PropertyValue<AlignmentType> value) {
if (value == getIconRotationAlignment())
return;
- impl->layout.iconRotationAlignment.set(value);
+ impl->layout.unevaluated.get<IconRotationAlignment>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "icon-rotation-alignment");
}
PropertyValue<float> SymbolLayer::getDefaultIconSize() {
- return { 1 };
+ return IconSize::defaultValue();
}
PropertyValue<float> SymbolLayer::getIconSize() const {
- return impl->layout.iconSize.get();
+ return impl->layout.unevaluated.get<IconSize>();
}
void SymbolLayer::setIconSize(PropertyValue<float> value) {
if (value == getIconSize())
return;
- impl->layout.iconSize.set(value);
+ impl->layout.unevaluated.get<IconSize>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "icon-size");
}
PropertyValue<IconTextFitType> SymbolLayer::getDefaultIconTextFit() {
- return { IconTextFitType::None };
+ return IconTextFit::defaultValue();
}
PropertyValue<IconTextFitType> SymbolLayer::getIconTextFit() const {
- return impl->layout.iconTextFit.get();
+ return impl->layout.unevaluated.get<IconTextFit>();
}
void SymbolLayer::setIconTextFit(PropertyValue<IconTextFitType> value) {
if (value == getIconTextFit())
return;
- impl->layout.iconTextFit.set(value);
+ impl->layout.unevaluated.get<IconTextFit>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "icon-text-fit");
}
PropertyValue<std::array<float, 4>> SymbolLayer::getDefaultIconTextFitPadding() {
- return { {{ 0, 0, 0, 0 }} };
+ return IconTextFitPadding::defaultValue();
}
PropertyValue<std::array<float, 4>> SymbolLayer::getIconTextFitPadding() const {
- return impl->layout.iconTextFitPadding.get();
+ return impl->layout.unevaluated.get<IconTextFitPadding>();
}
void SymbolLayer::setIconTextFitPadding(PropertyValue<std::array<float, 4>> value) {
if (value == getIconTextFitPadding())
return;
- impl->layout.iconTextFitPadding.set(value);
+ impl->layout.unevaluated.get<IconTextFitPadding>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "icon-text-fit-padding");
}
PropertyValue<std::string> SymbolLayer::getDefaultIconImage() {
- return { "" };
+ return IconImage::defaultValue();
}
PropertyValue<std::string> SymbolLayer::getIconImage() const {
- return impl->layout.iconImage.get();
+ return impl->layout.unevaluated.get<IconImage>();
}
void SymbolLayer::setIconImage(PropertyValue<std::string> value) {
if (value == getIconImage())
return;
- impl->layout.iconImage.set(value);
+ impl->layout.unevaluated.get<IconImage>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "icon-image");
}
PropertyValue<float> SymbolLayer::getDefaultIconRotate() {
- return { 0 };
+ return IconRotate::defaultValue();
}
PropertyValue<float> SymbolLayer::getIconRotate() const {
- return impl->layout.iconRotate.get();
+ return impl->layout.unevaluated.get<IconRotate>();
}
void SymbolLayer::setIconRotate(PropertyValue<float> value) {
if (value == getIconRotate())
return;
- impl->layout.iconRotate.set(value);
+ impl->layout.unevaluated.get<IconRotate>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "icon-rotate");
}
PropertyValue<float> SymbolLayer::getDefaultIconPadding() {
- return { 2 };
+ return IconPadding::defaultValue();
}
PropertyValue<float> SymbolLayer::getIconPadding() const {
- return impl->layout.iconPadding.get();
+ return impl->layout.unevaluated.get<IconPadding>();
}
void SymbolLayer::setIconPadding(PropertyValue<float> value) {
if (value == getIconPadding())
return;
- impl->layout.iconPadding.set(value);
+ impl->layout.unevaluated.get<IconPadding>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "icon-padding");
}
PropertyValue<bool> SymbolLayer::getDefaultIconKeepUpright() {
- return { false };
+ return IconKeepUpright::defaultValue();
}
PropertyValue<bool> SymbolLayer::getIconKeepUpright() const {
- return impl->layout.iconKeepUpright.get();
+ return impl->layout.unevaluated.get<IconKeepUpright>();
}
void SymbolLayer::setIconKeepUpright(PropertyValue<bool> value) {
if (value == getIconKeepUpright())
return;
- impl->layout.iconKeepUpright.set(value);
+ impl->layout.unevaluated.get<IconKeepUpright>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "icon-keep-upright");
}
PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultIconOffset() {
- return { {{ 0, 0 }} };
+ return IconOffset::defaultValue();
}
PropertyValue<std::array<float, 2>> SymbolLayer::getIconOffset() const {
- return impl->layout.iconOffset.get();
+ return impl->layout.unevaluated.get<IconOffset>();
}
void SymbolLayer::setIconOffset(PropertyValue<std::array<float, 2>> value) {
if (value == getIconOffset())
return;
- impl->layout.iconOffset.set(value);
+ impl->layout.unevaluated.get<IconOffset>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "icon-offset");
}
PropertyValue<AlignmentType> SymbolLayer::getDefaultTextPitchAlignment() {
- return { AlignmentType::Auto };
+ return TextPitchAlignment::defaultValue();
}
PropertyValue<AlignmentType> SymbolLayer::getTextPitchAlignment() const {
- return impl->layout.textPitchAlignment.get();
+ return impl->layout.unevaluated.get<TextPitchAlignment>();
}
void SymbolLayer::setTextPitchAlignment(PropertyValue<AlignmentType> value) {
if (value == getTextPitchAlignment())
return;
- impl->layout.textPitchAlignment.set(value);
+ impl->layout.unevaluated.get<TextPitchAlignment>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-pitch-alignment");
}
PropertyValue<AlignmentType> SymbolLayer::getDefaultTextRotationAlignment() {
- return { AlignmentType::Auto };
+ return TextRotationAlignment::defaultValue();
}
PropertyValue<AlignmentType> SymbolLayer::getTextRotationAlignment() const {
- return impl->layout.textRotationAlignment.get();
+ return impl->layout.unevaluated.get<TextRotationAlignment>();
}
void SymbolLayer::setTextRotationAlignment(PropertyValue<AlignmentType> value) {
if (value == getTextRotationAlignment())
return;
- impl->layout.textRotationAlignment.set(value);
+ impl->layout.unevaluated.get<TextRotationAlignment>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-rotation-alignment");
}
PropertyValue<std::string> SymbolLayer::getDefaultTextField() {
- return { "" };
+ return TextField::defaultValue();
}
PropertyValue<std::string> SymbolLayer::getTextField() const {
- return impl->layout.textField.get();
+ return impl->layout.unevaluated.get<TextField>();
}
void SymbolLayer::setTextField(PropertyValue<std::string> value) {
if (value == getTextField())
return;
- impl->layout.textField.set(value);
+ impl->layout.unevaluated.get<TextField>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-field");
}
PropertyValue<std::vector<std::string>> SymbolLayer::getDefaultTextFont() {
- return { { "Open Sans Regular", "Arial Unicode MS Regular" } };
+ return TextFont::defaultValue();
}
PropertyValue<std::vector<std::string>> SymbolLayer::getTextFont() const {
- return impl->layout.textFont.get();
+ return impl->layout.unevaluated.get<TextFont>();
}
void SymbolLayer::setTextFont(PropertyValue<std::vector<std::string>> value) {
if (value == getTextFont())
return;
- impl->layout.textFont.set(value);
+ impl->layout.unevaluated.get<TextFont>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-font");
}
PropertyValue<float> SymbolLayer::getDefaultTextSize() {
- return { 16 };
+ return TextSize::defaultValue();
}
PropertyValue<float> SymbolLayer::getTextSize() const {
- return impl->layout.textSize.get();
+ return impl->layout.unevaluated.get<TextSize>();
}
void SymbolLayer::setTextSize(PropertyValue<float> value) {
if (value == getTextSize())
return;
- impl->layout.textSize.set(value);
+ impl->layout.unevaluated.get<TextSize>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-size");
}
PropertyValue<float> SymbolLayer::getDefaultTextMaxWidth() {
- return { 10 };
+ return TextMaxWidth::defaultValue();
}
PropertyValue<float> SymbolLayer::getTextMaxWidth() const {
- return impl->layout.textMaxWidth.get();
+ return impl->layout.unevaluated.get<TextMaxWidth>();
}
void SymbolLayer::setTextMaxWidth(PropertyValue<float> value) {
if (value == getTextMaxWidth())
return;
- impl->layout.textMaxWidth.set(value);
+ impl->layout.unevaluated.get<TextMaxWidth>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-max-width");
}
PropertyValue<float> SymbolLayer::getDefaultTextLineHeight() {
- return { 1.2 };
+ return TextLineHeight::defaultValue();
}
PropertyValue<float> SymbolLayer::getTextLineHeight() const {
- return impl->layout.textLineHeight.get();
+ return impl->layout.unevaluated.get<TextLineHeight>();
}
void SymbolLayer::setTextLineHeight(PropertyValue<float> value) {
if (value == getTextLineHeight())
return;
- impl->layout.textLineHeight.set(value);
+ impl->layout.unevaluated.get<TextLineHeight>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-line-height");
}
PropertyValue<float> SymbolLayer::getDefaultTextLetterSpacing() {
- return { 0 };
+ return TextLetterSpacing::defaultValue();
}
PropertyValue<float> SymbolLayer::getTextLetterSpacing() const {
- return impl->layout.textLetterSpacing.get();
+ return impl->layout.unevaluated.get<TextLetterSpacing>();
}
void SymbolLayer::setTextLetterSpacing(PropertyValue<float> value) {
if (value == getTextLetterSpacing())
return;
- impl->layout.textLetterSpacing.set(value);
+ impl->layout.unevaluated.get<TextLetterSpacing>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-letter-spacing");
}
PropertyValue<TextJustifyType> SymbolLayer::getDefaultTextJustify() {
- return { TextJustifyType::Center };
+ return TextJustify::defaultValue();
}
PropertyValue<TextJustifyType> SymbolLayer::getTextJustify() const {
- return impl->layout.textJustify.get();
+ return impl->layout.unevaluated.get<TextJustify>();
}
void SymbolLayer::setTextJustify(PropertyValue<TextJustifyType> value) {
if (value == getTextJustify())
return;
- impl->layout.textJustify.set(value);
+ impl->layout.unevaluated.get<TextJustify>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-justify");
}
PropertyValue<TextAnchorType> SymbolLayer::getDefaultTextAnchor() {
- return { TextAnchorType::Center };
+ return TextAnchor::defaultValue();
}
PropertyValue<TextAnchorType> SymbolLayer::getTextAnchor() const {
- return impl->layout.textAnchor.get();
+ return impl->layout.unevaluated.get<TextAnchor>();
}
void SymbolLayer::setTextAnchor(PropertyValue<TextAnchorType> value) {
if (value == getTextAnchor())
return;
- impl->layout.textAnchor.set(value);
+ impl->layout.unevaluated.get<TextAnchor>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-anchor");
}
PropertyValue<float> SymbolLayer::getDefaultTextMaxAngle() {
- return { 45 };
+ return TextMaxAngle::defaultValue();
}
PropertyValue<float> SymbolLayer::getTextMaxAngle() const {
- return impl->layout.textMaxAngle.get();
+ return impl->layout.unevaluated.get<TextMaxAngle>();
}
void SymbolLayer::setTextMaxAngle(PropertyValue<float> value) {
if (value == getTextMaxAngle())
return;
- impl->layout.textMaxAngle.set(value);
+ impl->layout.unevaluated.get<TextMaxAngle>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-max-angle");
}
PropertyValue<float> SymbolLayer::getDefaultTextRotate() {
- return { 0 };
+ return TextRotate::defaultValue();
}
PropertyValue<float> SymbolLayer::getTextRotate() const {
- return impl->layout.textRotate.get();
+ return impl->layout.unevaluated.get<TextRotate>();
}
void SymbolLayer::setTextRotate(PropertyValue<float> value) {
if (value == getTextRotate())
return;
- impl->layout.textRotate.set(value);
+ impl->layout.unevaluated.get<TextRotate>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-rotate");
}
PropertyValue<float> SymbolLayer::getDefaultTextPadding() {
- return { 2 };
+ return TextPadding::defaultValue();
}
PropertyValue<float> SymbolLayer::getTextPadding() const {
- return impl->layout.textPadding.get();
+ return impl->layout.unevaluated.get<TextPadding>();
}
void SymbolLayer::setTextPadding(PropertyValue<float> value) {
if (value == getTextPadding())
return;
- impl->layout.textPadding.set(value);
+ impl->layout.unevaluated.get<TextPadding>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-padding");
}
PropertyValue<bool> SymbolLayer::getDefaultTextKeepUpright() {
- return { true };
+ return TextKeepUpright::defaultValue();
}
PropertyValue<bool> SymbolLayer::getTextKeepUpright() const {
- return impl->layout.textKeepUpright.get();
+ return impl->layout.unevaluated.get<TextKeepUpright>();
}
void SymbolLayer::setTextKeepUpright(PropertyValue<bool> value) {
if (value == getTextKeepUpright())
return;
- impl->layout.textKeepUpright.set(value);
+ impl->layout.unevaluated.get<TextKeepUpright>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-keep-upright");
}
PropertyValue<TextTransformType> SymbolLayer::getDefaultTextTransform() {
- return { TextTransformType::None };
+ return TextTransform::defaultValue();
}
PropertyValue<TextTransformType> SymbolLayer::getTextTransform() const {
- return impl->layout.textTransform.get();
+ return impl->layout.unevaluated.get<TextTransform>();
}
void SymbolLayer::setTextTransform(PropertyValue<TextTransformType> value) {
if (value == getTextTransform())
return;
- impl->layout.textTransform.set(value);
+ impl->layout.unevaluated.get<TextTransform>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-transform");
}
PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultTextOffset() {
- return { {{ 0, 0 }} };
+ return TextOffset::defaultValue();
}
PropertyValue<std::array<float, 2>> SymbolLayer::getTextOffset() const {
- return impl->layout.textOffset.get();
+ return impl->layout.unevaluated.get<TextOffset>();
}
void SymbolLayer::setTextOffset(PropertyValue<std::array<float, 2>> value) {
if (value == getTextOffset())
return;
- impl->layout.textOffset.set(value);
+ impl->layout.unevaluated.get<TextOffset>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-offset");
}
PropertyValue<bool> SymbolLayer::getDefaultTextAllowOverlap() {
- return { false };
+ return TextAllowOverlap::defaultValue();
}
PropertyValue<bool> SymbolLayer::getTextAllowOverlap() const {
- return impl->layout.textAllowOverlap.get();
+ return impl->layout.unevaluated.get<TextAllowOverlap>();
}
void SymbolLayer::setTextAllowOverlap(PropertyValue<bool> value) {
if (value == getTextAllowOverlap())
return;
- impl->layout.textAllowOverlap.set(value);
+ impl->layout.unevaluated.get<TextAllowOverlap>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-allow-overlap");
}
PropertyValue<bool> SymbolLayer::getDefaultTextIgnorePlacement() {
- return { false };
+ return TextIgnorePlacement::defaultValue();
}
PropertyValue<bool> SymbolLayer::getTextIgnorePlacement() const {
- return impl->layout.textIgnorePlacement.get();
+ return impl->layout.unevaluated.get<TextIgnorePlacement>();
}
void SymbolLayer::setTextIgnorePlacement(PropertyValue<bool> value) {
if (value == getTextIgnorePlacement())
return;
- impl->layout.textIgnorePlacement.set(value);
+ impl->layout.unevaluated.get<TextIgnorePlacement>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-ignore-placement");
}
PropertyValue<bool> SymbolLayer::getDefaultTextOptional() {
- return { false };
+ return TextOptional::defaultValue();
}
PropertyValue<bool> SymbolLayer::getTextOptional() const {
- return impl->layout.textOptional.get();
+ return impl->layout.unevaluated.get<TextOptional>();
}
void SymbolLayer::setTextOptional(PropertyValue<bool> value) {
if (value == getTextOptional())
return;
- impl->layout.textOptional.set(value);
+ impl->layout.unevaluated.get<TextOptional>() = value;
impl->observer->onLayerLayoutPropertyChanged(*this, "text-optional");
}
@@ -543,13 +547,13 @@ PropertyValue<float> SymbolLayer::getDefaultIconOpacity() {
}
PropertyValue<float> SymbolLayer::getIconOpacity(const optional<std::string>& klass) const {
- return impl->paint.iconOpacity.get(klass);
+ return impl->paint.get<IconOpacity>(klass);
}
void SymbolLayer::setIconOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getIconOpacity(klass))
return;
- impl->paint.iconOpacity.set(value, klass);
+ impl->paint.set<IconOpacity>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -558,13 +562,13 @@ PropertyValue<Color> SymbolLayer::getDefaultIconColor() {
}
PropertyValue<Color> SymbolLayer::getIconColor(const optional<std::string>& klass) const {
- return impl->paint.iconColor.get(klass);
+ return impl->paint.get<IconColor>(klass);
}
void SymbolLayer::setIconColor(PropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getIconColor(klass))
return;
- impl->paint.iconColor.set(value, klass);
+ impl->paint.set<IconColor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -573,13 +577,13 @@ PropertyValue<Color> SymbolLayer::getDefaultIconHaloColor() {
}
PropertyValue<Color> SymbolLayer::getIconHaloColor(const optional<std::string>& klass) const {
- return impl->paint.iconHaloColor.get(klass);
+ return impl->paint.get<IconHaloColor>(klass);
}
void SymbolLayer::setIconHaloColor(PropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getIconHaloColor(klass))
return;
- impl->paint.iconHaloColor.set(value, klass);
+ impl->paint.set<IconHaloColor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -588,13 +592,13 @@ PropertyValue<float> SymbolLayer::getDefaultIconHaloWidth() {
}
PropertyValue<float> SymbolLayer::getIconHaloWidth(const optional<std::string>& klass) const {
- return impl->paint.iconHaloWidth.get(klass);
+ return impl->paint.get<IconHaloWidth>(klass);
}
void SymbolLayer::setIconHaloWidth(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getIconHaloWidth(klass))
return;
- impl->paint.iconHaloWidth.set(value, klass);
+ impl->paint.set<IconHaloWidth>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -603,13 +607,13 @@ PropertyValue<float> SymbolLayer::getDefaultIconHaloBlur() {
}
PropertyValue<float> SymbolLayer::getIconHaloBlur(const optional<std::string>& klass) const {
- return impl->paint.iconHaloBlur.get(klass);
+ return impl->paint.get<IconHaloBlur>(klass);
}
void SymbolLayer::setIconHaloBlur(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getIconHaloBlur(klass))
return;
- impl->paint.iconHaloBlur.set(value, klass);
+ impl->paint.set<IconHaloBlur>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -618,13 +622,13 @@ PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultIconTranslate() {
}
PropertyValue<std::array<float, 2>> SymbolLayer::getIconTranslate(const optional<std::string>& klass) const {
- return impl->paint.iconTranslate.get(klass);
+ return impl->paint.get<IconTranslate>(klass);
}
void SymbolLayer::setIconTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) {
if (value == getIconTranslate(klass))
return;
- impl->paint.iconTranslate.set(value, klass);
+ impl->paint.set<IconTranslate>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -633,13 +637,13 @@ PropertyValue<TranslateAnchorType> SymbolLayer::getDefaultIconTranslateAnchor()
}
PropertyValue<TranslateAnchorType> SymbolLayer::getIconTranslateAnchor(const optional<std::string>& klass) const {
- return impl->paint.iconTranslateAnchor.get(klass);
+ return impl->paint.get<IconTranslateAnchor>(klass);
}
void SymbolLayer::setIconTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) {
if (value == getIconTranslateAnchor(klass))
return;
- impl->paint.iconTranslateAnchor.set(value, klass);
+ impl->paint.set<IconTranslateAnchor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -648,13 +652,13 @@ PropertyValue<float> SymbolLayer::getDefaultTextOpacity() {
}
PropertyValue<float> SymbolLayer::getTextOpacity(const optional<std::string>& klass) const {
- return impl->paint.textOpacity.get(klass);
+ return impl->paint.get<TextOpacity>(klass);
}
void SymbolLayer::setTextOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getTextOpacity(klass))
return;
- impl->paint.textOpacity.set(value, klass);
+ impl->paint.set<TextOpacity>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -663,13 +667,13 @@ PropertyValue<Color> SymbolLayer::getDefaultTextColor() {
}
PropertyValue<Color> SymbolLayer::getTextColor(const optional<std::string>& klass) const {
- return impl->paint.textColor.get(klass);
+ return impl->paint.get<TextColor>(klass);
}
void SymbolLayer::setTextColor(PropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getTextColor(klass))
return;
- impl->paint.textColor.set(value, klass);
+ impl->paint.set<TextColor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -678,13 +682,13 @@ PropertyValue<Color> SymbolLayer::getDefaultTextHaloColor() {
}
PropertyValue<Color> SymbolLayer::getTextHaloColor(const optional<std::string>& klass) const {
- return impl->paint.textHaloColor.get(klass);
+ return impl->paint.get<TextHaloColor>(klass);
}
void SymbolLayer::setTextHaloColor(PropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getTextHaloColor(klass))
return;
- impl->paint.textHaloColor.set(value, klass);
+ impl->paint.set<TextHaloColor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -693,13 +697,13 @@ PropertyValue<float> SymbolLayer::getDefaultTextHaloWidth() {
}
PropertyValue<float> SymbolLayer::getTextHaloWidth(const optional<std::string>& klass) const {
- return impl->paint.textHaloWidth.get(klass);
+ return impl->paint.get<TextHaloWidth>(klass);
}
void SymbolLayer::setTextHaloWidth(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getTextHaloWidth(klass))
return;
- impl->paint.textHaloWidth.set(value, klass);
+ impl->paint.set<TextHaloWidth>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -708,13 +712,13 @@ PropertyValue<float> SymbolLayer::getDefaultTextHaloBlur() {
}
PropertyValue<float> SymbolLayer::getTextHaloBlur(const optional<std::string>& klass) const {
- return impl->paint.textHaloBlur.get(klass);
+ return impl->paint.get<TextHaloBlur>(klass);
}
void SymbolLayer::setTextHaloBlur(PropertyValue<float> value, const optional<std::string>& klass) {
if (value == getTextHaloBlur(klass))
return;
- impl->paint.textHaloBlur.set(value, klass);
+ impl->paint.set<TextHaloBlur>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -723,13 +727,13 @@ PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultTextTranslate() {
}
PropertyValue<std::array<float, 2>> SymbolLayer::getTextTranslate(const optional<std::string>& klass) const {
- return impl->paint.textTranslate.get(klass);
+ return impl->paint.get<TextTranslate>(klass);
}
void SymbolLayer::setTextTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) {
if (value == getTextTranslate(klass))
return;
- impl->paint.textTranslate.set(value, klass);
+ impl->paint.set<TextTranslate>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
@@ -738,13 +742,13 @@ PropertyValue<TranslateAnchorType> SymbolLayer::getDefaultTextTranslateAnchor()
}
PropertyValue<TranslateAnchorType> SymbolLayer::getTextTranslateAnchor(const optional<std::string>& klass) const {
- return impl->paint.textTranslateAnchor.get(klass);
+ return impl->paint.get<TextTranslateAnchor>(klass);
}
void SymbolLayer::setTextTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) {
if (value == getTextTranslateAnchor(klass))
return;
- impl->paint.textTranslateAnchor.set(value, klass);
+ impl->paint.set<TextTranslateAnchor>(value, klass);
impl->observer->onLayerPaintPropertyChanged(*this);
}
diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp
index e85f3a90f9..f058598f5f 100644
--- a/src/mbgl/style/layers/symbol_layer_impl.cpp
+++ b/src/mbgl/style/layers/symbol_layer_impl.cpp
@@ -10,71 +10,102 @@ void SymbolLayer::Impl::cascade(const CascadeParameters& parameters) {
paint.cascade(parameters);
}
-bool SymbolLayer::Impl::recalculate(const CalculationParameters& parameters) {
- bool hasTransitions = paint.recalculate(parameters);
+bool SymbolLayer::Impl::evaluate(const PropertyEvaluationParameters& parameters) {
+ paint.evaluate(parameters);
// text-size and icon-size are layout properties but they also need to be evaluated as paint properties:
- layout.iconSize.calculate(parameters);
- layout.textSize.calculate(parameters);
- iconSize = layout.iconSize;
- textSize = layout.textSize;
+ iconSize = layout.evaluate<IconSize>(parameters);
+ textSize = layout.evaluate<TextSize>(parameters);
- passes = ((paint.iconOpacity > 0 && (paint.iconColor.value.a > 0 || paint.iconHaloColor.value.a > 0) && iconSize > 0)
- || (paint.textOpacity > 0 && (paint.textColor.value.a > 0 || paint.textHaloColor.value.a > 0) && textSize > 0))
+ passes = ((paint.evaluated.get<IconOpacity>() > 0 && (paint.evaluated.get<IconColor>().a > 0 || paint.evaluated.get<IconHaloColor>().a > 0) && iconSize > 0)
+ || (paint.evaluated.get<TextOpacity>() > 0 && (paint.evaluated.get<TextColor>().a > 0 || paint.evaluated.get<TextHaloColor>().a > 0) && textSize > 0))
? RenderPass::Translucent : RenderPass::None;
- return hasTransitions;
+ return paint.hasTransition();
}
-std::unique_ptr<Bucket> SymbolLayer::Impl::createBucket(BucketParameters&) const {
+std::unique_ptr<Bucket> SymbolLayer::Impl::createBucket(BucketParameters&, const GeometryTileLayer&) const {
assert(false); // Should be calling createLayout() instead.
return nullptr;
}
-std::unique_ptr<SymbolLayout> SymbolLayer::Impl::createLayout(BucketParameters& parameters) const {
- SymbolLayoutProperties layoutProperties = layout;
+std::unique_ptr<SymbolLayout> SymbolLayer::Impl::createLayout(BucketParameters& parameters,
+ const GeometryTileLayer& layer,
+ std::vector<std::string> group) const {
+ PropertyEvaluationParameters p(parameters.tileID.overscaledZ);
+ SymbolLayoutProperties::Evaluated evaluated = layout.evaluate(p);
- CalculationParameters p(parameters.tileID.overscaledZ);
- layoutProperties.recalculate(p);
-
- if (layoutProperties.iconRotationAlignment.value == AlignmentType::Auto) {
- if (layoutProperties.symbolPlacement.value == SymbolPlacementType::Line) {
- layoutProperties.iconRotationAlignment.value = AlignmentType::Map;
+ if (evaluated.get<IconRotationAlignment>() == AlignmentType::Auto) {
+ if (evaluated.get<SymbolPlacement>() == SymbolPlacementType::Line) {
+ evaluated.get<IconRotationAlignment>() = AlignmentType::Map;
} else {
- layoutProperties.iconRotationAlignment.value = AlignmentType::Viewport;
+ evaluated.get<IconRotationAlignment>() = AlignmentType::Viewport;
}
}
- if (layoutProperties.textRotationAlignment.value == AlignmentType::Auto) {
- if (layoutProperties.symbolPlacement.value == SymbolPlacementType::Line) {
- layoutProperties.textRotationAlignment.value = AlignmentType::Map;
+ if (evaluated.get<TextRotationAlignment>() == AlignmentType::Auto) {
+ if (evaluated.get<SymbolPlacement>() == SymbolPlacementType::Line) {
+ evaluated.get<TextRotationAlignment>() = AlignmentType::Map;
} else {
- layoutProperties.textRotationAlignment.value = AlignmentType::Viewport;
+ evaluated.get<TextRotationAlignment>() = AlignmentType::Viewport;
}
}
// If unspecified `text-pitch-alignment` inherits `text-rotation-alignment`
- if (layoutProperties.textPitchAlignment.value == AlignmentType::Auto) {
- layoutProperties.textPitchAlignment.value = layoutProperties.textRotationAlignment.value;
+ if (evaluated.get<TextPitchAlignment>() == AlignmentType::Auto) {
+ evaluated.get<TextPitchAlignment>() = evaluated.get<TextRotationAlignment>();
}
- layoutProperties.textSize.calculate(CalculationParameters(18));
- float textMaxSize = layoutProperties.textSize;
+ float textMaxSize = layout.evaluate<TextSize>(PropertyEvaluationParameters(18));
- layoutProperties.iconSize.calculate(CalculationParameters(p.z + 1));
- layoutProperties.textSize.calculate(CalculationParameters(p.z + 1));
+ evaluated.get<IconSize>() = layout.evaluate<IconSize>(PropertyEvaluationParameters(p.z + 1));
+ evaluated.get<TextSize>() = layout.evaluate<TextSize>(PropertyEvaluationParameters(p.z + 1));
- return std::make_unique<SymbolLayout>(id,
- parameters.layer.getName(),
+ return std::make_unique<SymbolLayout>(std::move(group),
+ layer.getName(),
parameters.tileID.overscaleFactor(),
parameters.tileID.overscaledZ,
parameters.mode,
- parameters.layer,
+ layer,
filter,
- layoutProperties,
+ evaluated,
textMaxSize,
*spriteAtlas);
}
+SymbolPropertyValues SymbolLayer::Impl::iconPropertyValues(const SymbolLayoutProperties::Evaluated& layout_) const {
+ return SymbolPropertyValues {
+ layout_.get<IconRotationAlignment>(), // icon-pitch-alignment is not yet implemented; inherit the rotation alignment
+ layout_.get<IconRotationAlignment>(),
+ layout_.get<IconSize>(),
+ paint.evaluated.get<IconOpacity>(),
+ paint.evaluated.get<IconColor>(),
+ paint.evaluated.get<IconHaloColor>(),
+ paint.evaluated.get<IconHaloWidth>(),
+ paint.evaluated.get<IconHaloBlur>(),
+ paint.evaluated.get<IconTranslate>(),
+ paint.evaluated.get<IconTranslateAnchor>(),
+ iconSize,
+ 1.0f
+ };
+}
+
+SymbolPropertyValues SymbolLayer::Impl::textPropertyValues(const SymbolLayoutProperties::Evaluated& layout_) const {
+ return SymbolPropertyValues {
+ layout_.get<TextPitchAlignment>(),
+ layout_.get<TextRotationAlignment>(),
+ layout_.get<TextSize>(),
+ paint.evaluated.get<TextOpacity>(),
+ paint.evaluated.get<TextColor>(),
+ paint.evaluated.get<TextHaloColor>(),
+ paint.evaluated.get<TextHaloWidth>(),
+ paint.evaluated.get<TextHaloBlur>(),
+ paint.evaluated.get<TextTranslate>(),
+ paint.evaluated.get<TextTranslateAnchor>(),
+ textSize,
+ 24.0f
+ };
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/symbol_layer_impl.hpp b/src/mbgl/style/layers/symbol_layer_impl.hpp
index fe37ba86ea..db18da07e2 100644
--- a/src/mbgl/style/layers/symbol_layer_impl.hpp
+++ b/src/mbgl/style/layers/symbol_layer_impl.hpp
@@ -11,16 +11,51 @@ class SymbolLayout;
namespace style {
+// Repackaging evaluated values from SymbolLayoutProperties + SymbolPaintProperties
+// for genericity over icons vs. text.
+class SymbolPropertyValues {
+public:
+ // Layout
+ AlignmentType pitchAlignment;
+ AlignmentType rotationAlignment;
+ float layoutSize;
+
+ // Paint
+ float opacity;
+ Color color;
+ Color haloColor;
+ float haloWidth;
+ float haloBlur;
+ std::array<float, 2> translate;
+ TranslateAnchorType translateAnchor;
+ float paintSize;
+
+ float sdfScale; // Constant (1.0 or 24.0)
+
+ bool hasHalo() const {
+ return haloColor.a > 0.0f && haloWidth > 0.0f;
+ }
+
+ bool hasForeground() const {
+ return color.a > 0.0f;
+ }
+};
+
class SymbolLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
- bool recalculate(const CalculationParameters&) override;
+ bool evaluate(const PropertyEvaluationParameters&) override;
+
+ std::unique_ptr<Bucket> createBucket(BucketParameters&, const GeometryTileLayer&) const override;
+ std::unique_ptr<SymbolLayout> createLayout(BucketParameters&, const GeometryTileLayer&,
+ std::vector<std::string>) const;
- std::unique_ptr<Bucket> createBucket(BucketParameters&) const override;
- std::unique_ptr<SymbolLayout> createLayout(BucketParameters&) const;
+ SymbolPropertyValues iconPropertyValues(const SymbolLayoutProperties::Evaluated&) const;
+ SymbolPropertyValues textPropertyValues(const SymbolLayoutProperties::Evaluated&) const;
SymbolLayoutProperties layout;
SymbolPaintProperties paint;
diff --git a/src/mbgl/style/layers/symbol_layer_properties.cpp b/src/mbgl/style/layers/symbol_layer_properties.cpp
index 59a73d3d59..5a1ce713ba 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.cpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.cpp
@@ -5,80 +5,5 @@
namespace mbgl {
namespace style {
-void SymbolLayoutProperties::recalculate(const CalculationParameters& parameters) {
- symbolPlacement.calculate(parameters);
- symbolSpacing.calculate(parameters);
- symbolAvoidEdges.calculate(parameters);
- iconAllowOverlap.calculate(parameters);
- iconIgnorePlacement.calculate(parameters);
- iconOptional.calculate(parameters);
- iconRotationAlignment.calculate(parameters);
- iconSize.calculate(parameters);
- iconTextFit.calculate(parameters);
- iconTextFitPadding.calculate(parameters);
- iconImage.calculate(parameters);
- iconRotate.calculate(parameters);
- iconPadding.calculate(parameters);
- iconKeepUpright.calculate(parameters);
- iconOffset.calculate(parameters);
- textPitchAlignment.calculate(parameters);
- textRotationAlignment.calculate(parameters);
- textField.calculate(parameters);
- textFont.calculate(parameters);
- textSize.calculate(parameters);
- textMaxWidth.calculate(parameters);
- textLineHeight.calculate(parameters);
- textLetterSpacing.calculate(parameters);
- textJustify.calculate(parameters);
- textAnchor.calculate(parameters);
- textMaxAngle.calculate(parameters);
- textRotate.calculate(parameters);
- textPadding.calculate(parameters);
- textKeepUpright.calculate(parameters);
- textTransform.calculate(parameters);
- textOffset.calculate(parameters);
- textAllowOverlap.calculate(parameters);
- textIgnorePlacement.calculate(parameters);
- textOptional.calculate(parameters);
-}
-
-void SymbolPaintProperties::cascade(const CascadeParameters& parameters) {
- iconOpacity.cascade(parameters);
- iconColor.cascade(parameters);
- iconHaloColor.cascade(parameters);
- iconHaloWidth.cascade(parameters);
- iconHaloBlur.cascade(parameters);
- iconTranslate.cascade(parameters);
- iconTranslateAnchor.cascade(parameters);
- textOpacity.cascade(parameters);
- textColor.cascade(parameters);
- textHaloColor.cascade(parameters);
- textHaloWidth.cascade(parameters);
- textHaloBlur.cascade(parameters);
- textTranslate.cascade(parameters);
- textTranslateAnchor.cascade(parameters);
-}
-
-bool SymbolPaintProperties::recalculate(const CalculationParameters& parameters) {
- bool hasTransitions = false;
-
- hasTransitions |= iconOpacity.calculate(parameters);
- hasTransitions |= iconColor.calculate(parameters);
- hasTransitions |= iconHaloColor.calculate(parameters);
- hasTransitions |= iconHaloWidth.calculate(parameters);
- hasTransitions |= iconHaloBlur.calculate(parameters);
- hasTransitions |= iconTranslate.calculate(parameters);
- hasTransitions |= iconTranslateAnchor.calculate(parameters);
- hasTransitions |= textOpacity.calculate(parameters);
- hasTransitions |= textColor.calculate(parameters);
- hasTransitions |= textHaloColor.calculate(parameters);
- hasTransitions |= textHaloWidth.calculate(parameters);
- hasTransitions |= textHaloBlur.calculate(parameters);
- hasTransitions |= textTranslate.calculate(parameters);
- hasTransitions |= textTranslateAnchor.calculate(parameters);
-
- return hasTransitions;
-}
-
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp
index fefa0ae05e..f5fd6ce3df 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.hpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.hpp
@@ -9,69 +9,285 @@
namespace mbgl {
namespace style {
-class CascadeParameters;
-class CalculationParameters;
-
-class SymbolLayoutProperties {
-public:
- void recalculate(const CalculationParameters&);
-
- LayoutProperty<SymbolPlacementType> symbolPlacement { SymbolPlacementType::Point };
- LayoutProperty<float> symbolSpacing { 250 };
- LayoutProperty<bool> symbolAvoidEdges { false };
- LayoutProperty<bool> iconAllowOverlap { false };
- LayoutProperty<bool> iconIgnorePlacement { false };
- LayoutProperty<bool> iconOptional { false };
- LayoutProperty<AlignmentType> iconRotationAlignment { AlignmentType::Auto };
- LayoutProperty<float> iconSize { 1 };
- LayoutProperty<IconTextFitType> iconTextFit { IconTextFitType::None };
- LayoutProperty<std::array<float, 4>> iconTextFitPadding { {{ 0, 0, 0, 0 }} };
- LayoutProperty<std::string> iconImage { "" };
- LayoutProperty<float> iconRotate { 0 };
- LayoutProperty<float> iconPadding { 2 };
- LayoutProperty<bool> iconKeepUpright { false };
- LayoutProperty<std::array<float, 2>> iconOffset { {{ 0, 0 }} };
- LayoutProperty<AlignmentType> textPitchAlignment { AlignmentType::Auto };
- LayoutProperty<AlignmentType> textRotationAlignment { AlignmentType::Auto };
- LayoutProperty<std::string> textField { "" };
- LayoutProperty<std::vector<std::string>> textFont { { "Open Sans Regular", "Arial Unicode MS Regular" } };
- LayoutProperty<float> textSize { 16 };
- LayoutProperty<float> textMaxWidth { 10 };
- LayoutProperty<float> textLineHeight { 1.2 };
- LayoutProperty<float> textLetterSpacing { 0 };
- LayoutProperty<TextJustifyType> textJustify { TextJustifyType::Center };
- LayoutProperty<TextAnchorType> textAnchor { TextAnchorType::Center };
- LayoutProperty<float> textMaxAngle { 45 };
- LayoutProperty<float> textRotate { 0 };
- LayoutProperty<float> textPadding { 2 };
- LayoutProperty<bool> textKeepUpright { true };
- LayoutProperty<TextTransformType> textTransform { TextTransformType::None };
- LayoutProperty<std::array<float, 2>> textOffset { {{ 0, 0 }} };
- LayoutProperty<bool> textAllowOverlap { false };
- LayoutProperty<bool> textIgnorePlacement { false };
- LayoutProperty<bool> textOptional { false };
-};
-
-class SymbolPaintProperties {
-public:
- void cascade(const CascadeParameters&);
- bool recalculate(const CalculationParameters&);
-
- PaintProperty<float> iconOpacity { 1 };
- PaintProperty<Color> iconColor { Color::black() };
- PaintProperty<Color> iconHaloColor { {} };
- PaintProperty<float> iconHaloWidth { 0 };
- PaintProperty<float> iconHaloBlur { 0 };
- PaintProperty<std::array<float, 2>> iconTranslate { {{ 0, 0 }} };
- PaintProperty<TranslateAnchorType> iconTranslateAnchor { TranslateAnchorType::Map };
- PaintProperty<float> textOpacity { 1 };
- PaintProperty<Color> textColor { Color::black() };
- PaintProperty<Color> textHaloColor { {} };
- PaintProperty<float> textHaloWidth { 0 };
- PaintProperty<float> textHaloBlur { 0 };
- PaintProperty<std::array<float, 2>> textTranslate { {{ 0, 0 }} };
- PaintProperty<TranslateAnchorType> textTranslateAnchor { TranslateAnchorType::Map };
+struct SymbolPlacement : LayoutProperty<SymbolPlacementType> {
+ static constexpr const char * key = "symbol-placement";
+ static SymbolPlacementType defaultValue() { return SymbolPlacementType::Point; }
};
+struct SymbolSpacing : LayoutProperty<float> {
+ static constexpr const char * key = "symbol-spacing";
+ static float defaultValue() { return 250; }
+};
+
+struct SymbolAvoidEdges : LayoutProperty<bool> {
+ static constexpr const char * key = "symbol-avoid-edges";
+ static bool defaultValue() { return false; }
+};
+
+struct IconAllowOverlap : LayoutProperty<bool> {
+ static constexpr const char * key = "icon-allow-overlap";
+ static bool defaultValue() { return false; }
+};
+
+struct IconIgnorePlacement : LayoutProperty<bool> {
+ static constexpr const char * key = "icon-ignore-placement";
+ static bool defaultValue() { return false; }
+};
+
+struct IconOptional : LayoutProperty<bool> {
+ static constexpr const char * key = "icon-optional";
+ static bool defaultValue() { return false; }
+};
+
+struct IconRotationAlignment : LayoutProperty<AlignmentType> {
+ static constexpr const char * key = "icon-rotation-alignment";
+ static AlignmentType defaultValue() { return AlignmentType::Auto; }
+};
+
+struct IconSize : LayoutProperty<float> {
+ static constexpr const char * key = "icon-size";
+ static float defaultValue() { return 1; }
+};
+
+struct IconTextFit : LayoutProperty<IconTextFitType> {
+ static constexpr const char * key = "icon-text-fit";
+ static IconTextFitType defaultValue() { return IconTextFitType::None; }
+};
+
+struct IconTextFitPadding : LayoutProperty<std::array<float, 4>> {
+ static constexpr const char * key = "icon-text-fit-padding";
+ static std::array<float, 4> defaultValue() { return {{ 0, 0, 0, 0 }}; }
+};
+
+struct IconImage : LayoutProperty<std::string> {
+ static constexpr const char * key = "icon-image";
+ static std::string defaultValue() { return ""; }
+};
+
+struct IconRotate : LayoutProperty<float> {
+ static constexpr const char * key = "icon-rotate";
+ static float defaultValue() { return 0; }
+};
+
+struct IconPadding : LayoutProperty<float> {
+ static constexpr const char * key = "icon-padding";
+ static float defaultValue() { return 2; }
+};
+
+struct IconKeepUpright : LayoutProperty<bool> {
+ static constexpr const char * key = "icon-keep-upright";
+ static bool defaultValue() { return false; }
+};
+
+struct IconOffset : LayoutProperty<std::array<float, 2>> {
+ static constexpr const char * key = "icon-offset";
+ static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+};
+
+struct TextPitchAlignment : LayoutProperty<AlignmentType> {
+ static constexpr const char * key = "text-pitch-alignment";
+ static AlignmentType defaultValue() { return AlignmentType::Auto; }
+};
+
+struct TextRotationAlignment : LayoutProperty<AlignmentType> {
+ static constexpr const char * key = "text-rotation-alignment";
+ static AlignmentType defaultValue() { return AlignmentType::Auto; }
+};
+
+struct TextField : LayoutProperty<std::string> {
+ static constexpr const char * key = "text-field";
+ static std::string defaultValue() { return ""; }
+};
+
+struct TextFont : LayoutProperty<std::vector<std::string>> {
+ static constexpr const char * key = "text-font";
+ static std::vector<std::string> defaultValue() { return { "Open Sans Regular", "Arial Unicode MS Regular" }; }
+};
+
+struct TextSize : LayoutProperty<float> {
+ static constexpr const char * key = "text-size";
+ static float defaultValue() { return 16; }
+};
+
+struct TextMaxWidth : LayoutProperty<float> {
+ static constexpr const char * key = "text-max-width";
+ static float defaultValue() { return 10; }
+};
+
+struct TextLineHeight : LayoutProperty<float> {
+ static constexpr const char * key = "text-line-height";
+ static float defaultValue() { return 1.2; }
+};
+
+struct TextLetterSpacing : LayoutProperty<float> {
+ static constexpr const char * key = "text-letter-spacing";
+ static float defaultValue() { return 0; }
+};
+
+struct TextJustify : LayoutProperty<TextJustifyType> {
+ static constexpr const char * key = "text-justify";
+ static TextJustifyType defaultValue() { return TextJustifyType::Center; }
+};
+
+struct TextAnchor : LayoutProperty<TextAnchorType> {
+ static constexpr const char * key = "text-anchor";
+ static TextAnchorType defaultValue() { return TextAnchorType::Center; }
+};
+
+struct TextMaxAngle : LayoutProperty<float> {
+ static constexpr const char * key = "text-max-angle";
+ static float defaultValue() { return 45; }
+};
+
+struct TextRotate : LayoutProperty<float> {
+ static constexpr const char * key = "text-rotate";
+ static float defaultValue() { return 0; }
+};
+
+struct TextPadding : LayoutProperty<float> {
+ static constexpr const char * key = "text-padding";
+ static float defaultValue() { return 2; }
+};
+
+struct TextKeepUpright : LayoutProperty<bool> {
+ static constexpr const char * key = "text-keep-upright";
+ static bool defaultValue() { return true; }
+};
+
+struct TextTransform : LayoutProperty<TextTransformType> {
+ static constexpr const char * key = "text-transform";
+ static TextTransformType defaultValue() { return TextTransformType::None; }
+};
+
+struct TextOffset : LayoutProperty<std::array<float, 2>> {
+ static constexpr const char * key = "text-offset";
+ static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+};
+
+struct TextAllowOverlap : LayoutProperty<bool> {
+ static constexpr const char * key = "text-allow-overlap";
+ static bool defaultValue() { return false; }
+};
+
+struct TextIgnorePlacement : LayoutProperty<bool> {
+ static constexpr const char * key = "text-ignore-placement";
+ static bool defaultValue() { return false; }
+};
+
+struct TextOptional : LayoutProperty<bool> {
+ static constexpr const char * key = "text-optional";
+ static bool defaultValue() { return false; }
+};
+
+struct IconOpacity : PaintProperty<float> {
+ static float defaultValue() { return 1; }
+};
+
+struct IconColor : PaintProperty<Color> {
+ static Color defaultValue() { return Color::black(); }
+};
+
+struct IconHaloColor : PaintProperty<Color> {
+ static Color defaultValue() { return {}; }
+};
+
+struct IconHaloWidth : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct IconHaloBlur : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct IconTranslate : PaintProperty<std::array<float, 2>> {
+ static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+};
+
+struct IconTranslateAnchor : PaintProperty<TranslateAnchorType> {
+ static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; }
+};
+
+struct TextOpacity : PaintProperty<float> {
+ static float defaultValue() { return 1; }
+};
+
+struct TextColor : PaintProperty<Color> {
+ static Color defaultValue() { return Color::black(); }
+};
+
+struct TextHaloColor : PaintProperty<Color> {
+ static Color defaultValue() { return {}; }
+};
+
+struct TextHaloWidth : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct TextHaloBlur : PaintProperty<float> {
+ static float defaultValue() { return 0; }
+};
+
+struct TextTranslate : PaintProperty<std::array<float, 2>> {
+ static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+};
+
+struct TextTranslateAnchor : PaintProperty<TranslateAnchorType> {
+ static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; }
+};
+
+class SymbolLayoutProperties : public LayoutProperties<
+ SymbolPlacement,
+ SymbolSpacing,
+ SymbolAvoidEdges,
+ IconAllowOverlap,
+ IconIgnorePlacement,
+ IconOptional,
+ IconRotationAlignment,
+ IconSize,
+ IconTextFit,
+ IconTextFitPadding,
+ IconImage,
+ IconRotate,
+ IconPadding,
+ IconKeepUpright,
+ IconOffset,
+ TextPitchAlignment,
+ TextRotationAlignment,
+ TextField,
+ TextFont,
+ TextSize,
+ TextMaxWidth,
+ TextLineHeight,
+ TextLetterSpacing,
+ TextJustify,
+ TextAnchor,
+ TextMaxAngle,
+ TextRotate,
+ TextPadding,
+ TextKeepUpright,
+ TextTransform,
+ TextOffset,
+ TextAllowOverlap,
+ TextIgnorePlacement,
+ TextOptional
+> {};
+
+class SymbolPaintProperties : public PaintProperties<
+ IconOpacity,
+ IconColor,
+ IconHaloColor,
+ IconHaloWidth,
+ IconHaloBlur,
+ IconTranslate,
+ IconTranslateAnchor,
+ TextOpacity,
+ TextColor,
+ TextHaloColor,
+ TextHaloWidth,
+ TextHaloBlur,
+ TextTranslate,
+ TextTranslateAnchor
+> {};
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layout_property.hpp b/src/mbgl/style/layout_property.hpp
index db1a1ebf28..6ea06ce556 100644
--- a/src/mbgl/style/layout_property.hpp
+++ b/src/mbgl/style/layout_property.hpp
@@ -1,43 +1,55 @@
#pragma once
-#include <mbgl/style/property_value.hpp>
-#include <mbgl/style/property_parsing.hpp>
#include <mbgl/style/property_evaluator.hpp>
-
-#include <utility>
+#include <mbgl/util/indexed_tuple.hpp>
namespace mbgl {
namespace style {
-template <typename T>
+class PropertyEvaluationParameters;
+
+template <class T>
class LayoutProperty {
public:
- explicit LayoutProperty(T v)
- : value(std::move(v)),
- defaultValue(value) {}
-
- const PropertyValue<T>& get() const {
- return currentValue;
- }
+ using EvaluatorType = PropertyEvaluator<T>;
+ using UnevaluatedType = PropertyValue<T>;
+ using EvaluatedType = T;
+};
- void set(const PropertyValue<T>& value_) {
- currentValue = value_;
+template <class... Ps>
+class LayoutProperties {
+public:
+ using Properties = TypeList<Ps...>;
+ using EvaluatedTypes = TypeList<typename Ps::EvaluatedType...>;
+ using UnevaluatedTypes = TypeList<typename Ps::UnevaluatedType...>;
+
+ template <class TypeList>
+ using Tuple = IndexedTuple<Properties, TypeList>;
+
+ class Evaluated : public Tuple<EvaluatedTypes> {
+ public:
+ using Tuple<EvaluatedTypes>::Tuple;
+ };
+
+ class Unevaluated : public Tuple<UnevaluatedTypes> {
+ public:
+ using Tuple<UnevaluatedTypes>::Tuple;
+ };
+
+ template <class P>
+ auto evaluate(const PropertyEvaluationParameters& parameters) const {
+ using Evaluator = typename P::EvaluatorType;
+ return unevaluated.template get<P>()
+ .evaluate(Evaluator(parameters, P::defaultValue()));
}
- void calculate(const CalculationParameters& parameters) {
- if (currentValue) {
- PropertyEvaluator<T> evaluator(parameters, defaultValue);
- value = PropertyValue<T>::visit(currentValue, evaluator);
- }
+ Evaluated evaluate(const PropertyEvaluationParameters& parameters) const {
+ return Evaluated {
+ evaluate<Ps>(parameters)...
+ };
}
- // TODO: remove / privatize
- operator T() const { return value; }
- T value;
-
-private:
- T defaultValue;
- PropertyValue<T> currentValue;
+ Unevaluated unevaluated;
};
} // namespace style
diff --git a/src/mbgl/style/paint_property.hpp b/src/mbgl/style/paint_property.hpp
index 4a620706ec..15df2a77c7 100644
--- a/src/mbgl/style/paint_property.hpp
+++ b/src/mbgl/style/paint_property.hpp
@@ -1,14 +1,15 @@
#pragma once
#include <mbgl/style/class_dictionary.hpp>
-#include <mbgl/style/property_parsing.hpp>
#include <mbgl/style/property_evaluator.hpp>
+#include <mbgl/style/cross_faded_property_evaluator.hpp>
#include <mbgl/style/transition_options.hpp>
#include <mbgl/style/cascade_parameters.hpp>
-#include <mbgl/style/calculation_parameters.hpp>
+#include <mbgl/style/property_evaluation_parameters.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/interpolate.hpp>
-#include <mbgl/util/rapidjson.hpp>
+#include <mbgl/util/indexed_tuple.hpp>
+#include <mbgl/util/ignore.hpp>
#include <unordered_map>
#include <utility>
@@ -16,29 +17,59 @@
namespace mbgl {
namespace style {
-template <class T, template <class S> class Evaluator = PropertyEvaluator>
-class PaintProperty {
+template <class T, class Evaluator>
+class UnevaluatedPaintProperty {
public:
- using Result = typename Evaluator<T>::ResultType;
+ using Result = typename Evaluator::ResultType;
+
+ UnevaluatedPaintProperty() = default;
+
+ UnevaluatedPaintProperty(PropertyValue<T> value_,
+ UnevaluatedPaintProperty<T, Evaluator> prior_,
+ TransitionOptions transition,
+ TimePoint now)
+ : begin(now + transition.delay.value_or(Duration::zero())),
+ end(begin + transition.duration.value_or(Duration::zero())),
+ value(std::move(value_)) {
+ if (transition) {
+ prior = { std::move(prior_) };
+ }
+ }
- explicit PaintProperty(T defaultValue_)
- : defaultValue(defaultValue_) {
- values.emplace(ClassID::Fallback, defaultValue_);
+ Result evaluate(const PropertyEvaluationParameters& parameters, T defaultValue) {
+ Result finalValue = value.evaluate(Evaluator(parameters, defaultValue));
+ if (!prior) {
+ // No prior value.
+ return finalValue;
+ } else if (parameters.now >= end) {
+ // Transition from prior value is now complete.
+ prior = {};
+ return finalValue;
+ } else {
+ // Interpolate between recursively-calculated prior value and final.
+ float t = std::chrono::duration<float>(parameters.now - begin) / (end - begin);
+ return util::interpolate(prior->get().evaluate(parameters, defaultValue), finalValue, util::DEFAULT_TRANSITION_EASE.solve(t, 0.001));
+ }
}
- PaintProperty(const PaintProperty& other)
- : defaultValue(other.defaultValue),
- values(other.values),
- transitions(other.transitions) {
+ bool hasTransition() const {
+ return bool(prior);
}
- PaintProperty& operator=(const PaintProperty& other) {
- defaultValue = other.defaultValue;
- values = other.values;
- transitions = other.transitions;
- return *this;
+ bool isUndefined() const {
+ return value.isUndefined();
}
+private:
+ optional<mapbox::util::recursive_wrapper<UnevaluatedPaintProperty<T, Evaluator>>> prior;
+ TimePoint begin;
+ TimePoint end;
+ PropertyValue<T> value;
+};
+
+template <class T>
+class CascadingPaintProperty {
+public:
bool isUndefined() const {
return values.find(ClassID::Default) == values.end();
}
@@ -57,82 +88,119 @@ public:
transitions[klass ? ClassDictionary::Get().lookup(*klass) : ClassID::Default] = transition;
}
- void cascade(const CascadeParameters& params) {
- const bool overrideTransition = !params.transition.delay && !params.transition.duration;
- Duration delay = params.transition.delay.value_or(Duration::zero());
- Duration duration = params.transition.duration.value_or(Duration::zero());
+ template <class UnevaluatedPaintProperty>
+ UnevaluatedPaintProperty cascade(const CascadeParameters& params, UnevaluatedPaintProperty prior) const {
+ TransitionOptions transition;
+ PropertyValue<T> value;
for (const auto classID : params.classes) {
- if (values.find(classID) == values.end())
- continue;
-
- if (overrideTransition && transitions.find(classID) != transitions.end()) {
- const TransitionOptions& transition = transitions[classID];
- if (transition.delay) delay = *transition.delay;
- if (transition.duration) duration = *transition.duration;
+ if (values.find(classID) != values.end()) {
+ value = values.at(classID);
+ break;
}
-
- cascaded = std::make_unique<CascadedValue>(std::move(cascaded),
- params.now + delay,
- params.now + delay + duration,
- values.at(classID));
-
- break;
}
- assert(cascaded);
- }
+ for (const auto classID : params.classes) {
+ if (transitions.find(classID) != transitions.end()) {
+ transition = transitions.at(classID).reverseMerge(transition);
+ break;
+ }
+ }
- bool calculate(const CalculationParameters& parameters) {
- assert(cascaded);
- Evaluator<T> evaluator(parameters, defaultValue);
- value = cascaded->calculate(evaluator, parameters.now);
- return cascaded->prior.operator bool();
+ return UnevaluatedPaintProperty(std::move(value),
+ std::move(prior),
+ transition.reverseMerge(params.transition),
+ params.now);
}
- // TODO: remove / privatize
- operator T() const { return value; }
- Result value;
-
private:
- T defaultValue;
std::unordered_map<ClassID, PropertyValue<T>> values;
std::unordered_map<ClassID, TransitionOptions> transitions;
+};
- struct CascadedValue {
- CascadedValue(std::unique_ptr<CascadedValue> prior_,
- TimePoint begin_,
- TimePoint end_,
- PropertyValue<T> value_)
- : prior(std::move(prior_)),
- begin(std::move(begin_)),
- end(std::move(end_)),
- value(std::move(value_)) {
- }
+template <class T>
+class PaintProperty {
+public:
+ using ValueType = PropertyValue<T>;
+ using CascadingType = CascadingPaintProperty<T>;
+ using EvaluatorType = PropertyEvaluator<T>;
+ using UnevaluatedType = UnevaluatedPaintProperty<T, EvaluatorType>;
+ using EvaluatedType = T;
+};
- Result calculate(const Evaluator<T>& evaluator, const TimePoint& now) {
- Result finalValue = PropertyValue<T>::visit(value, evaluator);
- if (!prior) {
- // No prior value.
- return finalValue;
- } else if (now >= end) {
- // Transition from prior value is now complete.
- prior.reset();
- return finalValue;
- } else {
- // Interpolate between recursively-calculated prior value and final.
- float t = std::chrono::duration<float>(now - begin) / (end - begin);
- return util::interpolate(prior->calculate(evaluator, now), finalValue, util::DEFAULT_TRANSITION_EASE.solve(t, 0.001));
- }
- }
+template <class T>
+class CrossFadedPaintProperty {
+public:
+ using ValueType = PropertyValue<T>;
+ using CascadingType = CascadingPaintProperty<T>;
+ using EvaluatorType = CrossFadedPropertyEvaluator<T>;
+ using UnevaluatedType = UnevaluatedPaintProperty<T, EvaluatorType>;
+ using EvaluatedType = Faded<T>;
+};
- std::unique_ptr<CascadedValue> prior;
- TimePoint begin;
- TimePoint end;
- PropertyValue<T> value;
+template <class... Ps>
+class PaintProperties {
+public:
+ using Properties = TypeList<Ps...>;
+ using EvaluatedTypes = TypeList<typename Ps::EvaluatedType...>;
+ using UnevaluatedTypes = TypeList<typename Ps::UnevaluatedType...>;
+ using CascadingTypes = TypeList<typename Ps::CascadingType...>;
+
+ template <class TypeList>
+ using Tuple = IndexedTuple<Properties, TypeList>;
+
+ class Evaluated : public Tuple<EvaluatedTypes> {
+ public:
+ using Tuple<EvaluatedTypes>::Tuple;
+ };
+
+ class Unevaluated : public Tuple<UnevaluatedTypes> {
+ public:
+ using Tuple<UnevaluatedTypes>::Tuple;
};
- std::unique_ptr<CascadedValue> cascaded;
+ class Cascading : public Tuple<CascadingTypes> {
+ public:
+ using Tuple<CascadingTypes>::Tuple;
+ };
+
+ template <class P>
+ auto get(const optional<std::string>& klass) const {
+ return cascading.template get<P>().get(klass);
+ }
+
+ template <class P>
+ void set(const typename P::ValueType& value, const optional<std::string>& klass) {
+ cascading.template get<P>().set(value, klass);
+ }
+
+ void cascade(const CascadeParameters& parameters) {
+ unevaluated = Unevaluated {
+ cascading.template get<Ps>().cascade(parameters,
+ std::move(unevaluated.template get<Ps>()))...
+ };
+ }
+
+ template <class P>
+ auto evaluate(const PropertyEvaluationParameters& parameters) {
+ return unevaluated.template get<P>().evaluate(parameters, P::defaultValue());
+ }
+
+ void evaluate(const PropertyEvaluationParameters& parameters) {
+ evaluated = Evaluated {
+ evaluate<Ps>(parameters)...
+ };
+ }
+
+ bool hasTransition() const {
+ bool result = false;
+ util::ignore({ result |= unevaluated.template get<Ps>().hasTransition()... });
+ return result;
+ }
+
+ Cascading cascading;
+ Unevaluated unevaluated;
+ Evaluated evaluated;
};
} // namespace style
diff --git a/src/mbgl/style/parser.cpp b/src/mbgl/style/parser.cpp
index 059082980d..c6c6e50dd7 100644
--- a/src/mbgl/style/parser.cpp
+++ b/src/mbgl/style/parser.cpp
@@ -5,7 +5,7 @@
#include <mbgl/style/conversion/source.hpp>
#include <mbgl/style/conversion/layer.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mapbox/geojsonvt.hpp>
diff --git a/src/mbgl/style/calculation_parameters.hpp b/src/mbgl/style/property_evaluation_parameters.hpp
index e1f059c524..2591fc07a1 100644
--- a/src/mbgl/style/calculation_parameters.hpp
+++ b/src/mbgl/style/property_evaluation_parameters.hpp
@@ -6,12 +6,12 @@
namespace mbgl {
namespace style {
-class CalculationParameters {
+class PropertyEvaluationParameters {
public:
- explicit CalculationParameters(float z_)
+ explicit PropertyEvaluationParameters(float z_)
: z(z_) {}
- CalculationParameters(float z_,
+ PropertyEvaluationParameters(float z_,
TimePoint now_,
ZoomHistory zoomHistory_,
Duration defaultFadeDuration_)
diff --git a/src/mbgl/style/property_evaluator.cpp b/src/mbgl/style/property_evaluator.cpp
deleted file mode 100644
index abb3681efa..0000000000
--- a/src/mbgl/style/property_evaluator.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-#include <mbgl/style/property_evaluator.hpp>
-#include <mbgl/style/calculation_parameters.hpp>
-#include <mbgl/style/types.hpp>
-#include <mbgl/util/interpolate.hpp>
-#include <mbgl/util/chrono.hpp>
-#include <mbgl/util/color.hpp>
-
-#include <cmath>
-
-namespace mbgl {
-namespace style {
-
-template <typename T>
-T defaultStopsValue();
-
-template <> bool defaultStopsValue() { return true; }
-template <> float defaultStopsValue() { return 1.0f; }
-template <> Color defaultStopsValue() { return { 0, 0, 0, 1 }; }
-template <> std::vector<float> defaultStopsValue() { return {{ 1, 0 }}; }
-template <> std::vector<std::string> defaultStopsValue() { return {{}}; }
-template <> std::array<float, 2> defaultStopsValue() { return {{ 0, 0 }}; }
-template <> std::array<float, 4> defaultStopsValue() { return {{ 0, 0, 0, 0 }}; }
-
-template <> std::string defaultStopsValue() { return {}; }
-template <> TranslateAnchorType defaultStopsValue() { return {}; }
-template <> RotateAnchorType defaultStopsValue() { return {}; }
-template <> CirclePitchScaleType defaultStopsValue() { return {}; }
-template <> LineCapType defaultStopsValue() { return {}; }
-template <> LineJoinType defaultStopsValue() { return {}; }
-template <> SymbolPlacementType defaultStopsValue() { return {}; }
-template <> TextAnchorType defaultStopsValue() { return {}; }
-template <> TextJustifyType defaultStopsValue() { return {}; }
-template <> TextTransformType defaultStopsValue() { return {}; }
-template <> AlignmentType defaultStopsValue() { return {}; }
-template <> IconTextFitType defaultStopsValue() { return {}; };
-
-template <typename T>
-T PropertyEvaluator<T>::operator()(const Function<T>& fn) const {
- float base = fn.getBase();
- const std::vector<std::pair<float, T>>& stops = fn.getStops();
- float z = parameters.z;
- bool smaller = false;
- float smaller_z = 0.0f;
- T smaller_val = T();
- bool larger = false;
- float larger_z = 0.0f;
- T larger_val = T();
-
- for (uint32_t i = 0; i < stops.size(); i++) {
- float stop_z = stops[i].first;
- T stop_val = stops[i].second;
- if (stop_z <= z && (!smaller || smaller_z < stop_z)) {
- smaller = true;
- smaller_z = stop_z;
- smaller_val = stop_val;
- }
- if (stop_z >= z && (!larger || larger_z > stop_z)) {
- larger = true;
- larger_z = stop_z;
- larger_val = stop_val;
- }
- }
-
- if (smaller && larger) {
- if (larger_z == smaller_z || larger_val == smaller_val) {
- return smaller_val;
- }
- const float zoomDiff = larger_z - smaller_z;
- const float zoomProgress = z - smaller_z;
- if (base == 1.0f) {
- const float t = zoomProgress / zoomDiff;
- return util::interpolate(smaller_val, larger_val, t);
- } else {
- const float t = (std::pow(base, zoomProgress) - 1) / (std::pow(base, zoomDiff) - 1);
- return util::interpolate(smaller_val, larger_val, t);
- }
- } else if (larger) {
- return larger_val;
- } else if (smaller) {
- return smaller_val;
- } else {
- // No stop defined.
- return defaultStopsValue<T>();
- }
-}
-
-template class PropertyEvaluator<bool>;
-template class PropertyEvaluator<float>;
-template class PropertyEvaluator<Color>;
-template class PropertyEvaluator<std::vector<float>>;
-template class PropertyEvaluator<std::vector<std::string>>;
-template class PropertyEvaluator<std::array<float, 2>>;
-template class PropertyEvaluator<std::array<float, 4>>;
-
-template class PropertyEvaluator<std::string>;
-template class PropertyEvaluator<TranslateAnchorType>;
-template class PropertyEvaluator<RotateAnchorType>;
-template class PropertyEvaluator<CirclePitchScaleType>;
-template class PropertyEvaluator<LineCapType>;
-template class PropertyEvaluator<LineJoinType>;
-template class PropertyEvaluator<SymbolPlacementType>;
-template class PropertyEvaluator<TextAnchorType>;
-template class PropertyEvaluator<TextJustifyType>;
-template class PropertyEvaluator<TextTransformType>;
-template class PropertyEvaluator<AlignmentType>;
-template class PropertyEvaluator<IconTextFitType>;
-
-template <typename T>
-Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const Undefined&) const {
- return calculate(defaultValue, defaultValue, defaultValue);
-}
-
-template <typename T>
-Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const T& constant) const {
- return calculate(constant, constant, constant);
-}
-
-template <typename T>
-T getBiggestStopLessThan(const Function<T>& function, float z) {
- const auto& stops = function.getStops();
- for (uint32_t i = 0; i < stops.size(); i++) {
- if (stops[i].first > z) {
- return stops[i == 0 ? i : i - 1].second;
- }
- }
- return stops.at(stops.size() - 1).second;
-}
-
-template <typename T>
-Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const Function<T>& function) const {
- return calculate(getBiggestStopLessThan(function, parameters.z - 1.0f),
- getBiggestStopLessThan(function, parameters.z),
- getBiggestStopLessThan(function, parameters.z + 1.0f));
-}
-
-template <typename T>
-Faded<T> CrossFadedPropertyEvaluator<T>::calculate(const T& min, const T& mid, const T& max) const {
- const float z = parameters.z;
- const float fraction = z - std::floor(z);
- const std::chrono::duration<float> d = parameters.defaultFadeDuration;
- const float t = std::min((parameters.now - parameters.zoomHistory.lastIntegerZoomTime) / d, 1.0f);
-
- return z > parameters.zoomHistory.lastIntegerZoom
- ? Faded<T> { min, mid, 2.0f, 1.0f, fraction + (1.0f - fraction) * t }
- : Faded<T> { max, mid, 0.5f, 1.0f, 1 - (1 - t) * fraction };
-}
-
-template class CrossFadedPropertyEvaluator<std::string>;
-template class CrossFadedPropertyEvaluator<std::vector<float>>;
-
-} // namespace style
-} // namespace mbgl
diff --git a/src/mbgl/style/property_evaluator.hpp b/src/mbgl/style/property_evaluator.hpp
index a0bce2f499..ca4962d948 100644
--- a/src/mbgl/style/property_evaluator.hpp
+++ b/src/mbgl/style/property_evaluator.hpp
@@ -1,66 +1,28 @@
#pragma once
#include <mbgl/style/property_value.hpp>
-#include <mbgl/util/interpolate.hpp>
+#include <mbgl/style/property_evaluation_parameters.hpp>
namespace mbgl {
namespace style {
-class CalculationParameters;
-
template <typename T>
class PropertyEvaluator {
public:
using ResultType = T;
- PropertyEvaluator(const CalculationParameters& parameters_, T defaultValue_)
+ PropertyEvaluator(const PropertyEvaluationParameters& parameters_, T defaultValue_)
: parameters(parameters_),
defaultValue(std::move(defaultValue_)) {}
T operator()(const Undefined&) const { return defaultValue; }
T operator()(const T& constant) const { return constant; }
- T operator()(const Function<T>&) const;
+ T operator()(const Function<T>& fn) const { return fn.evaluate(parameters.z); }
private:
- const CalculationParameters& parameters;
- T defaultValue;
-};
-
-template <typename T>
-struct Faded {
- T from;
- T to;
- float fromScale;
- float toScale;
- float t;
-};
-
-template <typename T>
-class CrossFadedPropertyEvaluator {
-public:
- using ResultType = Faded<T>;
-
- CrossFadedPropertyEvaluator(const CalculationParameters& parameters_, T defaultValue_)
- : parameters(parameters_),
- defaultValue(std::move(defaultValue_)) {}
-
- Faded<T> operator()(const Undefined&) const;
- Faded<T> operator()(const T& constant) const;
- Faded<T> operator()(const Function<T>&) const;
-
-private:
- Faded<T> calculate(const T& min, const T& mid, const T& max) const;
-
- const CalculationParameters& parameters;
+ const PropertyEvaluationParameters& parameters;
T defaultValue;
};
} // namespace style
-
-namespace util {
-template <typename T>
-struct Interpolator<style::Faded<T>>
- : Uninterpolated {};
-} // namespace util
-
} // namespace mbgl
diff --git a/src/mbgl/style/property_parsing.hpp b/src/mbgl/style/property_parsing.hpp
index 8c2bd2c0f4..b542c8ae47 100644
--- a/src/mbgl/style/property_parsing.hpp
+++ b/src/mbgl/style/property_parsing.hpp
@@ -5,7 +5,7 @@
#include <mbgl/style/rapidjson_conversion.hpp>
#include <mbgl/style/conversion/property_value.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
namespace mbgl {
namespace style {
diff --git a/src/mbgl/style/source_impl.cpp b/src/mbgl/style/source_impl.cpp
index d0ae54092d..149bf99f9d 100644
--- a/src/mbgl/style/source_impl.cpp
+++ b/src/mbgl/style/source_impl.cpp
@@ -6,7 +6,7 @@
#include <mbgl/style/update_parameters.hpp>
#include <mbgl/style/query_parameters.hpp>
#include <mbgl/text/placement_config.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/math/clamp.hpp>
#include <mbgl/util/tile_cover.hpp>
#include <mbgl/util/enum.hpp>
@@ -70,11 +70,13 @@ void Source::Impl::startRender(algorithm::ClipIDGenerator& generator,
void Source::Impl::finishRender(Painter& painter) {
for (auto& pair : renderTiles) {
auto& tile = pair.second;
- painter.renderTileDebug(tile);
+ if (tile.used) {
+ painter.renderTileDebug(tile);
+ }
}
}
-const std::map<UnwrappedTileID, RenderTile>& Source::Impl::getRenderTiles() const {
+std::map<UnwrappedTileID, RenderTile>& Source::Impl::getRenderTiles() {
return renderTiles;
}
@@ -139,13 +141,26 @@ void Source::Impl::updateTiles(const UpdateParameters& parameters) {
if (type != SourceType::Annotations && cache.getSize() == 0) {
size_t conservativeCacheSize =
- std::max((float)parameters.transformState.getWidth() / util::tileSize, 1.0f) *
- std::max((float)parameters.transformState.getHeight() / util::tileSize, 1.0f) *
+ std::max((float)parameters.transformState.getSize().width / util::tileSize, 1.0f) *
+ std::max((float)parameters.transformState.getSize().height / util::tileSize, 1.0f) *
(parameters.transformState.getMaxZoom() - parameters.transformState.getMinZoom() + 1) *
0.5;
cache.setSize(conservativeCacheSize);
}
+ removeStaleTiles(retain);
+
+ const PlacementConfig config { parameters.transformState.getAngle(),
+ parameters.transformState.getPitch(),
+ parameters.debugOptions & MapDebugOptions::Collision };
+
+ for (auto& pair : tiles) {
+ pair.second->setPlacementConfig(config);
+ }
+}
+
+// Moves all tiles to the cache except for those specified in the retain set.
+void Source::Impl::removeStaleTiles(const std::set<OverscaledTileID>& retain) {
// Remove stale tiles. This goes through the (sorted!) tiles map and retain set in lockstep
// and removes items from tiles that don't have the corresponding key in the retain set.
auto tilesIt = tiles.begin();
@@ -162,13 +177,12 @@ void Source::Impl::updateTiles(const UpdateParameters& parameters) {
++retainIt;
}
}
+}
- const PlacementConfig config { parameters.transformState.getAngle(),
- parameters.transformState.getPitch(),
- parameters.debugOptions & MapDebugOptions::Collision };
-
- for (auto& pair : tiles) {
- pair.second->setPlacementConfig(config);
+void Source::Impl::removeTiles() {
+ renderTiles.clear();
+ if (!tiles.empty()) {
+ removeStaleTiles({});
}
}
@@ -196,7 +210,7 @@ std::unordered_map<std::string, std::vector<Feature>> Source::Impl::queryRendere
for (const auto& p : parameters.geometry) {
queryGeometry.push_back(TileCoordinate::fromScreenCoordinate(
- parameters.transformState, 0, { p.x, parameters.transformState.getHeight() - p.y }).p);
+ parameters.transformState, 0, { p.x, parameters.transformState.getSize().height - p.y }).p);
}
mapbox::geometry::box<double> box = mapbox::geometry::envelope(queryGeometry);
diff --git a/src/mbgl/style/source_impl.hpp b/src/mbgl/style/source_impl.hpp
index a4dd48444e..e6340ae1cb 100644
--- a/src/mbgl/style/source_impl.hpp
+++ b/src/mbgl/style/source_impl.hpp
@@ -63,7 +63,7 @@ public:
const TransformState&);
void finishRender(Painter&);
- const std::map<UnwrappedTileID, RenderTile>& getRenderTiles() const;
+ std::map<UnwrappedTileID, RenderTile>& getRenderTiles();
std::unordered_map<std::string, std::vector<Feature>>
queryRenderedFeatures(const QueryParameters&) const;
@@ -88,6 +88,7 @@ public:
protected:
void invalidateTiles();
+ void removeStaleTiles(const std::set<OverscaledTileID>&);
Source& base;
SourceObserver* observer = nullptr;
diff --git a/src/mbgl/style/sources/geojson_source_impl.cpp b/src/mbgl/style/sources/geojson_source_impl.cpp
index 5aa335a389..3f3bc879f7 100644
--- a/src/mbgl/style/sources/geojson_source_impl.cpp
+++ b/src/mbgl/style/sources/geojson_source_impl.cpp
@@ -1,4 +1,4 @@
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/source_observer.hpp>
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index d28963aa64..2d11d16b1f 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -8,6 +8,7 @@
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/background_layer_impl.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/raster_layer.hpp>
@@ -18,7 +19,7 @@
#include <mbgl/style/class_dictionary.hpp>
#include <mbgl/style/update_parameters.hpp>
#include <mbgl/style/cascade_parameters.hpp>
-#include <mbgl/style/calculation_parameters.hpp>
+#include <mbgl/style/property_evaluation_parameters.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/geometry/line_atlas.hpp>
@@ -26,7 +27,7 @@
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/string.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/math/minmax.hpp>
#include <algorithm>
@@ -38,9 +39,9 @@ static Observer nullObserver;
Style::Style(FileSource& fileSource_, float pixelRatio)
: fileSource(fileSource_),
- glyphAtlas(std::make_unique<GlyphAtlas>(2048, 2048, fileSource)),
- spriteAtlas(std::make_unique<SpriteAtlas>(1024, 1024, pixelRatio)),
- lineAtlas(std::make_unique<LineAtlas>(256, 512)),
+ glyphAtlas(std::make_unique<GlyphAtlas>(Size{ 2048, 2048 }, fileSource)),
+ spriteAtlas(std::make_unique<SpriteAtlas>(Size{ 1024, 1024 }, pixelRatio)),
+ lineAtlas(std::make_unique<LineAtlas>(Size{ 256, 512 })),
observer(&nullObserver) {
glyphAtlas->setObserver(this);
spriteAtlas->setObserver(this);
@@ -262,7 +263,9 @@ double Style::getDefaultPitch() const {
void Style::updateTiles(const UpdateParameters& parameters) {
for (const auto& source : sources) {
- source->baseImpl->updateTiles(parameters);
+ if (source->baseImpl->enabled) {
+ source->baseImpl->updateTiles(parameters);
+ }
}
}
@@ -275,8 +278,9 @@ void Style::updateSymbolDependentTiles() {
void Style::relayout() {
for (const auto& sourceID : updateBatch.sourceIDs) {
Source* source = getSource(sourceID);
- if (!source) continue;
- source->baseImpl->reloadTiles();
+ if (source && source->baseImpl->enabled) {
+ source->baseImpl->reloadTiles();
+ }
}
updateBatch.sourceIDs.clear();
}
@@ -291,7 +295,6 @@ void Style::cascade(const TimePoint& timePoint, MapMode mode) {
classIDs.push_back(ClassDictionary::Get().lookup(className));
}
classIDs.push_back(ClassID::Default);
- classIDs.push_back(ClassID::Fallback);
const CascadeParameters parameters {
classIDs,
@@ -305,13 +308,15 @@ void Style::cascade(const TimePoint& timePoint, MapMode mode) {
}
void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
+ // Disable all sources first. If we find an enabled layer that uses this source, we will
+ // re-enable it later.
for (const auto& source : sources) {
source->baseImpl->enabled = false;
}
zoomHistory.update(z, timePoint);
- const CalculationParameters parameters {
+ const PropertyEvaluationParameters parameters {
z,
mode == MapMode::Continuous ? timePoint : Clock::time_point::max(),
zoomHistory,
@@ -320,7 +325,7 @@ void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
hasPendingTransitions = false;
for (const auto& layer : layers) {
- const bool hasTransitions = layer->baseImpl->recalculate(parameters);
+ const bool hasTransitions = layer->baseImpl->evaluate(parameters);
// Disable this layer if it doesn't need to be rendered.
const bool needsRendering = layer->baseImpl->needsRendering(zoomHistory.lastZoom);
@@ -338,6 +343,13 @@ void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
}
}
}
+
+ // Remove the existing tiles if we didn't end up re-enabling the source.
+ for (const auto& source : sources) {
+ if (!source->baseImpl->enabled) {
+ source->baseImpl->removeTiles();
+ }
+ }
}
std::vector<const Source*> Style::getSources() const {
@@ -388,7 +400,7 @@ bool Style::isLoaded() const {
return true;
}
-RenderData Style::getRenderData(MapDebugOptions debugOptions) const {
+RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const {
RenderData result;
for (const auto& source : sources) {
@@ -397,6 +409,9 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions) const {
}
}
+ const bool isLeft = std::abs(angle) > M_PI_2;
+ const bool isBottom = angle < 0;
+
for (const auto& layer : layers) {
if (!layer->baseImpl->needsRendering(zoomHistory.lastZoom)) {
continue;
@@ -408,10 +423,10 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions) const {
result.order.emplace_back(*layer);
continue;
}
- const BackgroundPaintProperties& paint = background->impl->paint;
- if (layer.get() == layers[0].get() && paint.backgroundPattern.value.from.empty()) {
+ const BackgroundPaintProperties::Evaluated& paint = background->impl->paint.evaluated;
+ if (layer.get() == layers[0].get() && paint.get<BackgroundPattern>().from.empty()) {
// This is a solid background. We can use glClear().
- result.backgroundColor = paint.backgroundColor * paint.backgroundOpacity;
+ result.backgroundColor = paint.get<BackgroundColor>() * paint.get<BackgroundOpacity>();
} else {
// This is a textured background, or not the bottommost layer. We need to render it with a quad.
result.order.emplace_back(*layer);
@@ -430,8 +445,29 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions) const {
continue;
}
- for (auto& pair : source->baseImpl->getRenderTiles()) {
- auto& tile = pair.second;
+ auto& renderTiles = source->baseImpl->getRenderTiles();
+ const bool symbolLayer = layer->is<SymbolLayer>();
+
+ // Sort symbol tiles in opposite y position, so tiles with overlapping
+ // symbols are drawn on top of each other, with lower symbols being
+ // drawn on top of higher symbols.
+ std::vector<std::reference_wrapper<RenderTile>> sortedTiles;
+ std::transform(renderTiles.begin(), renderTiles.end(), std::back_inserter(sortedTiles),
+ [](auto& pair) { return std::ref(pair.second); });
+ if (symbolLayer) {
+ std::sort(sortedTiles.begin(), sortedTiles.end(),
+ [isLeft, isBottom](const RenderTile& a, const RenderTile& b) {
+ bool sortX = a.id.canonical.x > b.id.canonical.x;
+ bool sortW = a.id.wrap > b.id.wrap;
+ bool sortY = a.id.canonical.y > b.id.canonical.y;
+ return
+ a.id.canonical.y != b.id.canonical.y ? (isLeft ? sortY : !sortY) :
+ a.id.wrap != b.id.wrap ? (isBottom ? sortW : !sortW) : (isBottom ? sortX : !sortX);
+ });
+ }
+
+ for (auto& tileRef : sortedTiles) {
+ auto& tile = tileRef.get();
if (!tile.tile.isRenderable()) {
continue;
}
@@ -439,7 +475,7 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions) const {
// We're not clipping symbol layers, so when we have both parents and children of symbol
// layers, we drop all children in favor of their parent to avoid duplicate labels.
// See https://github.com/mapbox/mapbox-gl-native/issues/2482
- if (layer->is<SymbolLayer>()) {
+ if (symbolLayer) {
bool skip = false;
// Look back through the buckets we decided to render to find out whether there is
// already a bucket from this layer that is a parent of this tile. Tiles are ordered
@@ -458,6 +494,7 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions) const {
auto bucket = tile.tile.getBucket(*layer);
if (bucket) {
result.order.emplace_back(*layer, &tile, bucket);
+ tile.used = true;
}
}
}
diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp
index 1da22b8cf3..d46e80e8bf 100644
--- a/src/mbgl/style/style.hpp
+++ b/src/mbgl/style/style.hpp
@@ -93,7 +93,7 @@ public:
bool hasClass(const std::string&) const;
std::vector<std::string> getClasses() const;
- RenderData getRenderData(MapDebugOptions) const;
+ RenderData getRenderData(MapDebugOptions, float angle) const;
std::vector<Feature> queryRenderedFeatures(const QueryParameters&) const;
@@ -118,9 +118,9 @@ private:
// Defaults
std::string name;
LatLng defaultLatLng;
- double defaultZoom;
- double defaultBearing;
- double defaultPitch;
+ double defaultZoom = 0;
+ double defaultBearing = 0;
+ double defaultPitch = 0;
std::vector<std::unique_ptr<Layer>>::const_iterator findLayer(const std::string& layerID) const;
void reloadLayerSource(Layer&);
diff --git a/src/mbgl/text/bidi.hpp b/src/mbgl/text/bidi.hpp
new file mode 100644
index 0000000000..59d306489c
--- /dev/null
+++ b/src/mbgl/text/bidi.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <set>
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <mbgl/util/noncopyable.hpp>
+
+namespace mbgl {
+
+class BiDi;
+class BiDiImpl;
+
+std::u16string applyArabicShaping(const std::u16string&);
+
+class BiDi : private util::noncopyable {
+public:
+ BiDi();
+ ~BiDi();
+
+ std::vector<std::u16string> processText(const std::u16string&, std::set<std::size_t>);
+
+private:
+ void mergeParagraphLineBreaks(std::set<std::size_t>&);
+ std::vector<std::u16string> applyLineBreaking(std::set<std::size_t>);
+ std::u16string getLine(std::size_t start, std::size_t end);
+
+ std::unique_ptr<BiDiImpl> impl;
+};
+
+} // end namespace mbgl
diff --git a/src/mbgl/text/collision_tile.cpp b/src/mbgl/text/collision_tile.cpp
index e485fbf36c..368750c89f 100644
--- a/src/mbgl/text/collision_tile.cpp
+++ b/src/mbgl/text/collision_tile.cpp
@@ -1,5 +1,6 @@
#include <mbgl/text/collision_tile.hpp>
#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/math/log2.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/math/minmax.hpp>
@@ -167,7 +168,7 @@ Box CollisionTile::getTreeBox(const Point<float>& anchor, const CollisionBox& bo
};
}
-std::vector<IndexedSubfeature> CollisionTile::queryRenderedSymbols(const GeometryCoordinates& queryGeometry, float scale) {
+std::vector<IndexedSubfeature> CollisionTile::queryRenderedSymbols(const GeometryCoordinates& queryGeometry, float scale) const {
std::vector<IndexedSubfeature> result;
if (queryGeometry.empty() || (tree.empty() && ignoredTree.empty())) {
return result;
diff --git a/src/mbgl/text/collision_tile.hpp b/src/mbgl/text/collision_tile.hpp
index 186cd19d28..ea4324edaf 100644
--- a/src/mbgl/text/collision_tile.hpp
+++ b/src/mbgl/text/collision_tile.hpp
@@ -42,7 +42,7 @@ public:
float placeFeature(const CollisionFeature&, bool allowOverlap, bool avoidEdges);
void insertFeature(CollisionFeature&, float minPlacementScale, bool ignorePlacement);
- std::vector<IndexedSubfeature> queryRenderedSymbols(const GeometryCoordinates&, float scale);
+ std::vector<IndexedSubfeature> queryRenderedSymbols(const GeometryCoordinates&, float scale) const;
const PlacementConfig config;
diff --git a/src/mbgl/text/get_anchors.cpp b/src/mbgl/text/get_anchors.cpp
index ce45e05d9c..b912c7763e 100644
--- a/src/mbgl/text/get_anchors.cpp
+++ b/src/mbgl/text/get_anchors.cpp
@@ -72,6 +72,7 @@ Anchors getAnchors(const GeometryCoordinates &line, float spacing,
const float maxAngle, const float textLeft, const float textRight,
const float iconLeft, const float iconRight,
const float glyphSize, const float boxScale, const float overscaling) {
+ if (line.empty()) return {};
// Resample a line to get anchor points for labels and check that each
// potential label passes text-max-angle check and has enough froom to fit
diff --git a/src/mbgl/text/glyph.cpp b/src/mbgl/text/glyph.cpp
index a877d7a799..29929b73e6 100644
--- a/src/mbgl/text/glyph.cpp
+++ b/src/mbgl/text/glyph.cpp
@@ -3,7 +3,7 @@
namespace mbgl {
// Note: this only works for the BMP
-GlyphRange getGlyphRange(char32_t glyph) {
+GlyphRange getGlyphRange(char16_t glyph) {
unsigned start = (glyph/256) * 256;
unsigned end = (start + 255);
if (start > 65280) start = 65280;
diff --git a/src/mbgl/text/glyph.hpp b/src/mbgl/text/glyph.hpp
index 975dc4ad23..d07fbdff21 100644
--- a/src/mbgl/text/glyph.hpp
+++ b/src/mbgl/text/glyph.hpp
@@ -11,10 +11,10 @@
namespace mbgl {
// Note: this only works for the BMP
-GlyphRange getGlyphRange(char32_t glyph);
+GlyphRange getGlyphRange(char16_t glyph);
struct GlyphMetrics {
- operator bool() const {
+ explicit operator bool() const {
return !(width == 0 && height == 0 && advance == 0);
}
@@ -27,12 +27,20 @@ struct GlyphMetrics {
};
+inline bool operator==(const GlyphMetrics& lhs, const GlyphMetrics& rhs) {
+ return lhs.width == rhs.width &&
+ lhs.height == rhs.height &&
+ lhs.left == rhs.left &&
+ lhs.top == rhs.top &&
+ lhs.advance == rhs.advance;
+}
+
struct Glyph {
explicit Glyph() : rect(0, 0, 0, 0), metrics() {}
explicit Glyph(Rect<uint16_t> rect_, GlyphMetrics metrics_)
: rect(std::move(rect_)), metrics(std::move(metrics_)) {}
- operator bool() const {
+ explicit operator bool() const {
return metrics || rect.hasArea();
}
@@ -55,16 +63,16 @@ public:
class Shaping {
public:
explicit Shaping() : top(0), bottom(0), left(0), right(0) {}
- explicit Shaping(float x, float y, std::u32string text_)
+ explicit Shaping(float x, float y, std::u16string text_)
: text(std::move(text_)), top(y), bottom(y), left(x), right(x) {}
std::vector<PositionedGlyph> positionedGlyphs;
- std::u32string text;
+ std::u16string text;
int32_t top;
int32_t bottom;
int32_t left;
int32_t right;
- operator bool() const { return !positionedGlyphs.empty(); }
+ explicit operator bool() const { return !positionedGlyphs.empty(); }
};
class SDFGlyph {
diff --git a/src/mbgl/text/glyph_atlas.cpp b/src/mbgl/text/glyph_atlas.cpp
index 2f8c44db59..5d30dacdce 100644
--- a/src/mbgl/text/glyph_atlas.cpp
+++ b/src/mbgl/text/glyph_atlas.cpp
@@ -1,10 +1,9 @@
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/text/glyph_atlas_observer.hpp>
#include <mbgl/text/glyph_pbf.hpp>
-#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/context.hpp>
-#include <mbgl/platform/log.hpp>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/logging.hpp>
+#include <mbgl/util/platform.hpp>
#include <cassert>
#include <algorithm>
@@ -13,13 +12,11 @@ namespace mbgl {
static GlyphAtlasObserver nullObserver;
-GlyphAtlas::GlyphAtlas(uint16_t width_, uint16_t height_, FileSource& fileSource_)
- : width(width_),
- height(height_),
- fileSource(fileSource_),
+GlyphAtlas::GlyphAtlas(const Size size, FileSource& fileSource_)
+ : fileSource(fileSource_),
observer(&nullObserver),
- bin(width_, height_),
- data(std::make_unique<uint8_t[]>(width_ * height_)),
+ bin(size.width, size.height),
+ image(size),
dirty(true) {
}
@@ -84,7 +81,7 @@ void GlyphAtlas::setObserver(GlyphAtlasObserver* observer_) {
}
void GlyphAtlas::addGlyphs(uintptr_t tileUID,
- const std::u32string& text,
+ const std::u16string& text,
const FontStack& fontStack,
const GlyphSet& glyphSet,
GlyphPositions& face)
@@ -93,7 +90,7 @@ void GlyphAtlas::addGlyphs(uintptr_t tileUID,
const std::map<uint32_t, SDFGlyph>& sdfs = glyphSet.getSDFs();
- for (uint32_t chr : text)
+ for (char16_t chr : text)
{
auto sdf_it = sdfs.find(chr);
if (sdf_it == sdfs.end()) {
@@ -148,18 +145,18 @@ Rect<uint16_t> GlyphAtlas::addGlyph(uintptr_t tileUID,
return rect;
}
- assert(rect.x + rect.w <= width);
- assert(rect.y + rect.h <= height);
+ assert(rect.x + rect.w <= image.size.width);
+ assert(rect.y + rect.h <= image.size.height);
face.emplace(glyph.id, GlyphValue { rect, tileUID });
// Copy the bitmap
const uint8_t* source = reinterpret_cast<const uint8_t*>(glyph.bitmap.data());
for (uint32_t y = 0; y < buffered_height; y++) {
- uint32_t y1 = width * (rect.y + y + padding) + rect.x + padding;
+ uint32_t y1 = image.size.width * (rect.y + y + padding) + rect.x + padding;
uint32_t y2 = buffered_width * y;
for (uint32_t x = 0; x < buffered_width; x++) {
- data[y1 + x] = source[y2 + x];
+ image.data[y1 + x] = source[y2 + x];
}
}
@@ -181,9 +178,9 @@ void GlyphAtlas::removeGlyphs(uintptr_t tileUID) {
const Rect<uint16_t>& rect = value.rect;
// Clear out the bitmap.
- uint8_t *target = data.get();
+ uint8_t *target = image.data.get();
for (uint32_t y = 0; y < rect.h; y++) {
- uint32_t y1 = width * (rect.y + y) + rect.x;
+ uint32_t y1 = image.size.width * (rect.y + y) + rect.x;
for (uint32_t x = 0; x < rect.w; x++) {
target[y1 + x] = 0;
}
@@ -203,60 +200,25 @@ void GlyphAtlas::removeGlyphs(uintptr_t tileUID) {
}
}
+Size GlyphAtlas::getSize() const {
+ return image.size;
+}
+
void GlyphAtlas::upload(gl::Context& context, gl::TextureUnit unit) {
- if (dirty) {
- const bool first = !texture;
- bind(context, unit);
-
- std::lock_guard<std::mutex> lock(mtx);
-
- context.activeTexture = unit;
- if (first) {
- MBGL_CHECK_ERROR(glTexImage2D(
- GL_TEXTURE_2D, // GLenum target
- 0, // GLint level
- GL_ALPHA, // GLint internalformat
- width, // GLsizei width
- height, // GLsizei height
- 0, // GLint border
- GL_ALPHA, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- data.get() // const GLvoid* data
- ));
- } else {
- MBGL_CHECK_ERROR(glTexSubImage2D(
- GL_TEXTURE_2D, // GLenum target
- 0, // GLint level
- 0, // GLint xoffset
- 0, // GLint yoffset
- width, // GLsizei width
- height, // GLsizei height
- GL_ALPHA, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- data.get() // const GLvoid* data
- ));
- }
+ std::lock_guard<std::mutex> lock(mtx);
- dirty = false;
+ if (!texture) {
+ texture = context.createTexture(image, unit);
+ } else if (dirty) {
+ context.updateTexture(*texture, image, unit);
}
+
+ dirty = false;
}
void GlyphAtlas::bind(gl::Context& context, gl::TextureUnit unit) {
- if (!texture) {
- texture = context.createTexture();
- context.activeTexture = unit;
- context.texture[unit] = *texture;
-#if not MBGL_USE_GLES2
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
-#endif
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- } else if (context.texture[unit] != *texture) {
- context.activeTexture = unit;
- context.texture[unit] = *texture;
- }
+ upload(context, unit);
+ context.bindTexture(*texture, unit, gl::TextureFilter::Linear);
}
} // namespace mbgl
diff --git a/src/mbgl/text/glyph_atlas.hpp b/src/mbgl/text/glyph_atlas.hpp
index 84875bdd78..af14aace5b 100644
--- a/src/mbgl/text/glyph_atlas.hpp
+++ b/src/mbgl/text/glyph_atlas.hpp
@@ -8,6 +8,8 @@
#include <mbgl/util/font_stack.hpp>
#include <mbgl/util/exclusive.hpp>
#include <mbgl/util/work_queue.hpp>
+#include <mbgl/util/image.hpp>
+#include <mbgl/gl/texture.hpp>
#include <mbgl/gl/object.hpp>
#include <atomic>
@@ -30,7 +32,7 @@ class Context;
class GlyphAtlas : public util::noncopyable {
public:
- GlyphAtlas(uint16_t width, uint16_t height, FileSource&);
+ GlyphAtlas(Size, FileSource&);
~GlyphAtlas();
util::exclusive<GlyphSet> getGlyphSet(const FontStack&);
@@ -53,7 +55,7 @@ public:
void setObserver(GlyphAtlasObserver* observer);
void addGlyphs(uintptr_t tileUID,
- const std::u32string& text,
+ const std::u16string& text,
const FontStack&,
const GlyphSet&,
GlyphPositions&);
@@ -66,8 +68,7 @@ public:
// the texture is only bound when the data is out of date (=dirty).
void upload(gl::Context&, gl::TextureUnit unit);
- const uint16_t width;
- const uint16_t height;
+ Size getSize() const;
private:
void requestGlyphRange(const FontStack&, const GlyphRange&);
@@ -100,9 +101,9 @@ private:
std::mutex mtx;
BinPack<uint16_t> bin;
std::unordered_map<FontStack, std::map<uint32_t, GlyphValue>, FontStackHash> index;
- const std::unique_ptr<uint8_t[]> data;
+ const AlphaImage image;
std::atomic<bool> dirty;
- mbgl::optional<gl::UniqueTexture> texture;
+ mbgl::optional<gl::Texture> texture;
};
} // namespace mbgl
diff --git a/src/mbgl/text/glyph_set.cpp b/src/mbgl/text/glyph_set.cpp
index 0875a83850..f9a90f9bb0 100644
--- a/src/mbgl/text/glyph_set.cpp
+++ b/src/mbgl/text/glyph_set.cpp
@@ -1,7 +1,11 @@
-#include <mbgl/text/glyph_set.hpp>
-#include <mbgl/platform/log.hpp>
#include <mbgl/math/minmax.hpp>
+#include <mbgl/text/glyph_set.hpp>
+#include <mbgl/util/i18n.hpp>
+#include <mbgl/util/logging.hpp>
+#include <boost/algorithm/string.hpp>
+
+#include <algorithm>
#include <cassert>
namespace mbgl {
@@ -26,44 +30,46 @@ void GlyphSet::insert(uint32_t id, SDFGlyph&& glyph) {
}
}
-const std::map<uint32_t, SDFGlyph> &GlyphSet::getSDFs() const {
+const std::map<uint32_t, SDFGlyph>& GlyphSet::getSDFs() const {
return sdfs;
}
-const Shaping GlyphSet::getShaping(const std::u32string &string, const float maxWidth,
- const float lineHeight, const float horizontalAlign,
- const float verticalAlign, const float justify,
- const float spacing, const Point<float> &translate) const {
- Shaping shaping(translate.x * 24, translate.y * 24, string);
-
- // the y offset *should* be part of the font metadata
- const int32_t yOffset = -17;
-
- float x = 0;
- const float y = yOffset;
+const Shaping GlyphSet::getShaping(const std::u16string& logicalInput,
+ const float maxWidth,
+ const float lineHeight,
+ const float horizontalAlign,
+ const float verticalAlign,
+ const float justify,
+ const float spacing,
+ const Point<float>& translate,
+ BiDi& bidi) const {
- // Loop through all characters of this label and shape.
- for (uint32_t chr : string) {
- auto it = sdfs.find(chr);
- if (it != sdfs.end()) {
- shaping.positionedGlyphs.emplace_back(chr, x, y);
- x += it->second.metrics.advance + spacing;
- }
- }
+ // The string stored in shaping.text is used for finding duplicates, but may end up quite
+ // different from the glyphs that get shown
+ Shaping shaping(translate.x * 24, translate.y * 24, logicalInput);
- if (shaping.positionedGlyphs.empty())
- return shaping;
+ std::vector<std::u16string> reorderedLines =
+ bidi.processText(logicalInput,
+ determineLineBreaks(logicalInput, spacing, maxWidth));
- lineWrap(shaping, lineHeight, maxWidth, horizontalAlign, verticalAlign, justify, translate);
+ shapeLines(shaping, reorderedLines, spacing, lineHeight, horizontalAlign, verticalAlign,
+ justify, translate);
return shaping;
}
-void align(Shaping &shaping, const float justify, const float horizontalAlign,
- const float verticalAlign, const uint32_t maxLineLength, const float lineHeight,
- const uint32_t line, const Point<float> &translate) {
- const float shiftX = (justify - horizontalAlign) * maxLineLength + ::round(translate.x * 24/* one em */);
- const float shiftY = (-verticalAlign * (line + 1) + 0.5) * lineHeight + ::round(translate.y * 24/* one em */);
+void align(Shaping& shaping,
+ const float justify,
+ const float horizontalAlign,
+ const float verticalAlign,
+ const float maxLineLength,
+ const float lineHeight,
+ const std::size_t lineCount,
+ const Point<float>& translate) {
+ const float shiftX =
+ (justify - horizontalAlign) * maxLineLength + ::round(translate.x * 24 /* one em */);
+ const float shiftY =
+ (-verticalAlign * lineCount + 0.5) * lineHeight + ::round(translate.y * 24 /* one em */);
for (auto& glyph : shaping.positionedGlyphs) {
glyph.x += shiftX;
@@ -71,94 +77,215 @@ void align(Shaping &shaping, const float justify, const float horizontalAlign,
}
}
-void justifyLine(std::vector<PositionedGlyph> &positionedGlyphs, const std::map<uint32_t, SDFGlyph> &sdfs, uint32_t start,
- uint32_t end, float justify) {
- PositionedGlyph &glyph = positionedGlyphs[end];
+// justify left = 0, right = 1, center = .5
+void justifyLine(std::vector<PositionedGlyph>& positionedGlyphs,
+ const std::map<uint32_t, SDFGlyph>& sdfs,
+ std::size_t start,
+ std::size_t end,
+ float justify) {
+ if (!justify) {
+ return;
+ }
+
+ PositionedGlyph& glyph = positionedGlyphs[end];
auto it = sdfs.find(glyph.glyph);
if (it != sdfs.end()) {
const uint32_t lastAdvance = it->second.metrics.advance;
const float lineIndent = float(glyph.x + lastAdvance) * justify;
- for (uint32_t j = start; j <= end; j++) {
+ for (std::size_t j = start; j <= end; j++) {
positionedGlyphs[j].x -= lineIndent;
}
}
}
-void GlyphSet::lineWrap(Shaping &shaping, const float lineHeight, const float maxWidth,
- const float horizontalAlign, const float verticalAlign,
- const float justify, const Point<float> &translate) const {
- uint32_t lastSafeBreak = 0;
+float GlyphSet::determineAverageLineWidth(const std::u16string& logicalInput,
+ const float spacing,
+ float maxWidth) const {
+ float totalWidth = 0;
- uint32_t lengthBeforeCurrentLine = 0;
- uint32_t lineStartIndex = 0;
- uint32_t line = 0;
+ for (char16_t chr : logicalInput) {
+ auto it = sdfs.find(chr);
+ if (it != sdfs.end()) {
+ totalWidth += it->second.metrics.advance + spacing;
+ }
+ }
- uint32_t maxLineLength = 0;
+ int32_t targetLineCount = std::fmax(1, std::ceil(totalWidth / maxWidth));
+ return totalWidth / targetLineCount;
+}
+
+float calculateBadness(const float lineWidth, const float targetWidth, const float penalty, const bool isLastBreak) {
+ const float raggedness = std::pow(lineWidth - targetWidth, 2);
+ if (isLastBreak) {
+ // Favor finals lines shorter than average over longer than average
+ if (lineWidth < targetWidth) {
+ return raggedness / 2;
+ } else {
+ return raggedness * 2;
+ }
+ }
+ if (penalty < 0) {
+ return raggedness - std::pow(penalty, 2);
+ }
+ return raggedness + std::pow(penalty, 2);
+}
+
+float calculatePenalty(char16_t codePoint, char16_t nextCodePoint) {
+ float penalty = 0;
+ // Force break on newline
+ if (codePoint == 0x0a) {
+ penalty -= 10000;
+ }
+ // Penalize open parenthesis at end of line
+ if (codePoint == 0x28 || codePoint == 0xff08) {
+ penalty += 50;
+ }
- std::vector<PositionedGlyph> &positionedGlyphs = shaping.positionedGlyphs;
+ // Penalize close parenthesis at beginning of line
+ if (nextCodePoint == 0x29 || nextCodePoint == 0xff09) {
+ penalty += 50;
+ }
+
+ return penalty;
+}
+
+struct PotentialBreak {
+ PotentialBreak(const std::size_t p_index, const float p_x, const PotentialBreak* p_priorBreak, const float p_badness)
+ : index(p_index), x(p_x), priorBreak(p_priorBreak), badness(p_badness)
+ {}
+
+ const std::size_t index;
+ const float x;
+ const PotentialBreak* priorBreak;
+ const float badness;
+};
+
+
+PotentialBreak evaluateBreak(const std::size_t breakIndex, const float breakX, const float targetWidth, const std::list<PotentialBreak>& potentialBreaks, const float penalty, const bool isLastBreak) {
+ // We could skip evaluating breaks where the line length (breakX - priorBreak.x) > maxWidth
+ // ...but in fact we allow lines longer than maxWidth (if there's no break points)
+ // ...and when targetWidth and maxWidth are close, strictly enforcing maxWidth can give
+ // more lopsided results.
+
+ const PotentialBreak* bestPriorBreak = nullptr;
+ float bestBreakBadness = calculateBadness(breakX, targetWidth, penalty, isLastBreak);
+ for (const auto& potentialBreak : potentialBreaks) {
+ const float lineWidth = breakX - potentialBreak.x;
+ float breakBadness =
+ calculateBadness(lineWidth, targetWidth, penalty, isLastBreak) + potentialBreak.badness;
+ if (breakBadness <= bestBreakBadness) {
+ bestPriorBreak = &potentialBreak;
+ bestBreakBadness = breakBadness;
+ }
+ }
+
+ return PotentialBreak(breakIndex, breakX, bestPriorBreak, bestBreakBadness);
+}
+
+std::set<std::size_t> leastBadBreaks(const PotentialBreak& lastLineBreak) {
+ std::set<std::size_t> leastBadBreaks = { lastLineBreak.index };
+ const PotentialBreak* priorBreak = lastLineBreak.priorBreak;
+ while (priorBreak) {
+ leastBadBreaks.insert(priorBreak->index);
+ priorBreak = priorBreak->priorBreak;
+ }
+ return leastBadBreaks;
+}
+
+
+// We determine line breaks based on shaped text in logical order. Working in visual order would be
+// more intuitive, but we can't do that because the visual order may be changed by line breaks!
+std::set<std::size_t> GlyphSet::determineLineBreaks(const std::u16string& logicalInput,
+ const float spacing,
+ float maxWidth) const {
+ if (!maxWidth) {
+ return {};
+ }
+
+ if (logicalInput.empty()) {
+ return {};
+ }
+
+ const float targetWidth = determineAverageLineWidth(logicalInput, spacing, maxWidth);
+
+ std::list<PotentialBreak> potentialBreaks;
+ float currentX = 0;
+
+ for (std::size_t i = 0; i < logicalInput.size(); i++) {
+ const char16_t codePoint = logicalInput[i];
+ auto it = sdfs.find(codePoint);
+ if (it != sdfs.end() && !boost::algorithm::is_any_of(u" \t\n\v\f\r")(codePoint)) {
+ currentX += it->second.metrics.advance + spacing;
+ }
+
+ // Ideographic characters, spaces, and word-breaking punctuation that often appear without
+ // surrounding spaces.
+ if ((i < logicalInput.size() - 1) &&
+ (util::i18n::allowsWordBreaking(codePoint) || util::i18n::allowsIdeographicBreaking(codePoint))) {
+ potentialBreaks.push_back(evaluateBreak(i+1, currentX, targetWidth, potentialBreaks,
+ calculatePenalty(codePoint, logicalInput[i+1]),
+ false));
+ }
+ }
- if (maxWidth) {
- for (uint32_t i = 0; i < positionedGlyphs.size(); i++) {
- PositionedGlyph &shape = positionedGlyphs[i];
+ return leastBadBreaks(evaluateBreak(logicalInput.size(), currentX, targetWidth, potentialBreaks, 0, true));
+}
- shape.x -= lengthBeforeCurrentLine;
- shape.y += lineHeight * line;
+void GlyphSet::shapeLines(Shaping& shaping,
+ const std::vector<std::u16string>& lines,
+ const float spacing,
+ const float lineHeight,
+ const float horizontalAlign,
+ const float verticalAlign,
+ const float justify,
+ const Point<float>& translate) const {
- if (shape.x > maxWidth && lastSafeBreak > 0) {
+ // the y offset *should* be part of the font metadata
+ const int32_t yOffset = -17;
- uint32_t lineLength = positionedGlyphs[lastSafeBreak + 1].x;
- maxLineLength = util::max(lineLength, maxLineLength);
+ float x = 0;
+ float y = yOffset;
- for (uint32_t k = lastSafeBreak + 1; k <= i; k++) {
- positionedGlyphs[k].y += lineHeight;
- positionedGlyphs[k].x -= lineLength;
- }
+ float maxLineLength = 0;
- if (justify) {
- // Collapse invisible characters.
- uint32_t breakGlyph = positionedGlyphs[lastSafeBreak].glyph;
- uint32_t lineEnd = lastSafeBreak;
- if (breakGlyph == 0x20 /* space */
- || breakGlyph == 0x200b /* zero-width space */) {
- lineEnd--;
- }
+ for (std::u16string line : lines) {
+ // Collapse whitespace so it doesn't throw off justification
+ boost::algorithm::trim_if(line, boost::algorithm::is_any_of(u" \t\n\v\f\r"));
- justifyLine(positionedGlyphs, sdfs, lineStartIndex, lineEnd, justify);
- }
+ if (line.empty()) {
+ y += lineHeight; // Still need a line feed after empty line
+ continue;
+ }
- lineStartIndex = lastSafeBreak + 1;
- lastSafeBreak = 0;
- lengthBeforeCurrentLine += lineLength;
- line++;
+ std::size_t lineStartIndex = shaping.positionedGlyphs.size();
+ for (char16_t chr : line) {
+ auto it = sdfs.find(chr);
+ if (it == sdfs.end()) {
+ continue;
}
- // Spaces, plus word-breaking punctuation that often appears without surrounding spaces.
- if (shape.glyph == 0x20 /* space */
- || shape.glyph == 0x26 /* ampersand */
- || shape.glyph == 0x2b /* plus sign */
- || shape.glyph == 0x2d /* hyphen-minus */
- || shape.glyph == 0x2f /* solidus */
- || shape.glyph == 0xad /* soft hyphen */
- || shape.glyph == 0xb7 /* middle dot */
- || shape.glyph == 0x200b /* zero-width space */
- || shape.glyph == 0x2010 /* hyphen */
- || shape.glyph == 0x2013 /* en dash */) {
- lastSafeBreak = i;
- }
+ const SDFGlyph& glyph = it->second;
+ shaping.positionedGlyphs.emplace_back(chr, x, y);
+ x += glyph.metrics.advance + spacing;
}
- }
- const PositionedGlyph& lastPositionedGlyph = positionedGlyphs.back();
- const auto lastGlyphIt = sdfs.find(lastPositionedGlyph.glyph);
- assert(lastGlyphIt != sdfs.end());
- const uint32_t lastLineLength = lastPositionedGlyph.x + lastGlyphIt->second.metrics.advance;
- maxLineLength = std::max(maxLineLength, lastLineLength);
+ // Only justify if we placed at least one glyph
+ if (shaping.positionedGlyphs.size() != lineStartIndex) {
+ float lineLength = x - spacing; // Don't count trailing spacing
+ maxLineLength = util::max(lineLength, maxLineLength);
+
+ justifyLine(shaping.positionedGlyphs, sdfs, lineStartIndex,
+ shaping.positionedGlyphs.size() - 1, justify);
+ }
- const uint32_t height = (line + 1) * lineHeight;
+ x = 0;
+ y += lineHeight;
+ }
- justifyLine(positionedGlyphs, sdfs, lineStartIndex, uint32_t(positionedGlyphs.size()) - 1, justify);
- align(shaping, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line, translate);
+ align(shaping, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight,
+ lines.size(), translate);
+ const uint32_t height = lines.size() * lineHeight;
// Calculate the bounding box
shaping.top += -verticalAlign * height;
diff --git a/src/mbgl/text/glyph_set.hpp b/src/mbgl/text/glyph_set.hpp
index 37ffdb070a..3037cefca0 100644
--- a/src/mbgl/text/glyph_set.hpp
+++ b/src/mbgl/text/glyph_set.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <mbgl/text/bidi.hpp>
#include <mbgl/text/glyph.hpp>
#include <mbgl/util/geometry.hpp>
@@ -8,14 +9,34 @@ namespace mbgl {
class GlyphSet {
public:
void insert(uint32_t id, SDFGlyph&&);
- const std::map<uint32_t, SDFGlyph> &getSDFs() const;
- const Shaping getShaping(const std::u32string &string, float maxWidth, float lineHeight,
- float horizontalAlign, float verticalAlign, float justify,
- float spacing, const Point<float> &translate) const;
- void lineWrap(Shaping &shaping, float lineHeight, float maxWidth, float horizontalAlign,
- float verticalAlign, float justify, const Point<float> &translate) const;
+ const std::map<uint32_t, SDFGlyph>& getSDFs() const;
+ const Shaping getShaping(const std::u16string& string,
+ float maxWidth,
+ float lineHeight,
+ float horizontalAlign,
+ float verticalAlign,
+ float justify,
+ float spacing,
+ const Point<float>& translate,
+ BiDi& bidi) const;
private:
+ float determineAverageLineWidth(const std::u16string& logicalInput,
+ const float spacing,
+ float maxWidth) const;
+ std::set<std::size_t> determineLineBreaks(const std::u16string& logicalInput,
+ const float spacing,
+ float maxWidth) const;
+
+ void shapeLines(Shaping& shaping,
+ const std::vector<std::u16string>& lines,
+ const float spacing,
+ float lineHeight,
+ float horizontalAlign,
+ float verticalAlign,
+ float justify,
+ const Point<float>& translate) const;
+
std::map<uint32_t, SDFGlyph> sdfs;
};
diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp
index 3f142cd908..1a05e6f94f 100644
--- a/src/mbgl/text/quads.cpp
+++ b/src/mbgl/text/quads.cpp
@@ -14,7 +14,7 @@ using namespace style;
const float globalMinScale = 0.5f; // underscale by 1 zoom level
SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
- const GeometryCoordinates& line, const SymbolLayoutProperties& layout,
+ const GeometryCoordinates& line, const SymbolLayoutProperties::Evaluated& layout,
const style::SymbolPlacementType placement, const Shaping& shapedText) {
auto image = *(shapedIcon.image);
@@ -29,24 +29,24 @@ SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
Point<float> br;
Point<float> bl;
- if (layout.iconTextFit != IconTextFitType::None && shapedText) {
+ if (layout.get<IconTextFit>() != IconTextFitType::None && shapedText) {
auto iconWidth = right - left;
auto iconHeight = bottom - top;
- auto size = layout.textSize / 24.0f;
+ auto size = layout.get<TextSize>() / 24.0f;
auto textLeft = shapedText.left * size;
auto textRight = shapedText.right * size;
auto textTop = shapedText.top * size;
auto textBottom = shapedText.bottom * size;
auto textWidth = textRight - textLeft;
auto textHeight = textBottom - textTop;;
- auto padT = layout.iconTextFitPadding.value[0];
- auto padR = layout.iconTextFitPadding.value[1];
- auto padB = layout.iconTextFitPadding.value[2];
- auto padL = layout.iconTextFitPadding.value[3];
- auto offsetY = layout.iconTextFit == IconTextFitType::Width ? (textHeight - iconHeight) * 0.5 : 0;
- auto offsetX = layout.iconTextFit == IconTextFitType::Height ? (textWidth - iconWidth) * 0.5 : 0;
- auto width = layout.iconTextFit == IconTextFitType::Width || layout.iconTextFit == IconTextFitType::Both ? textWidth : iconWidth;
- auto height = layout.iconTextFit == IconTextFitType::Height || layout.iconTextFit == IconTextFitType::Both ? textHeight : iconHeight;
+ auto padT = layout.get<IconTextFitPadding>()[0];
+ auto padR = layout.get<IconTextFitPadding>()[1];
+ auto padB = layout.get<IconTextFitPadding>()[2];
+ auto padL = layout.get<IconTextFitPadding>()[3];
+ auto offsetY = layout.get<IconTextFit>() == IconTextFitType::Width ? (textHeight - iconHeight) * 0.5 : 0;
+ auto offsetX = layout.get<IconTextFit>() == IconTextFitType::Height ? (textWidth - iconWidth) * 0.5 : 0;
+ auto width = layout.get<IconTextFit>() == IconTextFitType::Width || layout.get<IconTextFit>() == IconTextFitType::Both ? textWidth : iconWidth;
+ auto height = layout.get<IconTextFit>() == IconTextFitType::Height || layout.get<IconTextFit>() == IconTextFitType::Both ? textHeight : iconHeight;
left = textLeft + offsetX - padL;
top = textTop + offsetY - padT;
right = textLeft + offsetX + padR + width;
@@ -62,7 +62,7 @@ SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
bl = {left, bottom};
}
- float angle = layout.iconRotate * util::DEG2RAD;
+ float angle = layout.get<IconRotate>() * util::DEG2RAD;
if (placement == style::SymbolPlacementType::Line) {
assert(static_cast<unsigned int>(anchor.segment) < line.size());
const GeometryCoordinate &prev= line[anchor.segment];
@@ -165,11 +165,11 @@ void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs, Anchor &
}
SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText,
- const float boxScale, const GeometryCoordinates& line, const SymbolLayoutProperties& layout,
+ const float boxScale, const GeometryCoordinates& line, const SymbolLayoutProperties::Evaluated& layout,
const style::SymbolPlacementType placement, const GlyphPositions& face) {
- const float textRotate = layout.textRotate * util::DEG2RAD;
- const bool keepUpright = layout.textKeepUpright;
+ const float textRotate = layout.get<TextRotate>() * util::DEG2RAD;
+ const bool keepUpright = layout.get<TextKeepUpright>();
SymbolQuads quads;
diff --git a/src/mbgl/text/quads.hpp b/src/mbgl/text/quads.hpp
index d4edbf9493..75fb53aade 100644
--- a/src/mbgl/text/quads.hpp
+++ b/src/mbgl/text/quads.hpp
@@ -2,6 +2,7 @@
#include <mbgl/text/glyph.hpp>
#include <mbgl/style/types.hpp>
+#include <mbgl/style/layers/symbol_layer_properties.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <vector>
@@ -11,10 +12,6 @@ namespace mbgl {
struct Anchor;
class PositionedIcon;
-namespace style {
-class SymbolLayoutProperties;
-} // namespace style
-
struct SymbolQuad {
explicit SymbolQuad(Point<float> tl_, Point<float> tr_, Point<float> bl_, Point<float> br_,
Rect<uint16_t> tex_, float anchorAngle_, float glyphAngle_, Point<float> anchorPoint_,
@@ -40,11 +37,11 @@ struct SymbolQuad {
typedef std::vector<SymbolQuad> SymbolQuads;
SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
- const GeometryCoordinates& line, const style::SymbolLayoutProperties&,
+ const GeometryCoordinates& line, const style::SymbolLayoutProperties::Evaluated&,
style::SymbolPlacementType placement, const Shaping& shapedText);
SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText,
- const float boxScale, const GeometryCoordinates& line, const style::SymbolLayoutProperties&,
+ const float boxScale, const GeometryCoordinates& line, const style::SymbolLayoutProperties::Evaluated&,
style::SymbolPlacementType placement, const GlyphPositions& face);
} // namespace mbgl
diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp
index 1091cd6e94..062066aaf4 100644
--- a/src/mbgl/text/shaping.cpp
+++ b/src/mbgl/text/shaping.cpp
@@ -3,9 +3,11 @@
namespace mbgl {
-PositionedIcon shapeIcon(const SpriteAtlasElement& image, const style::SymbolLayoutProperties& layout) {
- float dx = layout.iconOffset.value[0];
- float dy = layout.iconOffset.value[1];
+using namespace style;
+
+PositionedIcon shapeIcon(const SpriteAtlasElement& image, const SymbolLayoutProperties::Evaluated& layout) {
+ float dx = layout.get<IconOffset>()[0];
+ float dy = layout.get<IconOffset>()[1];
float x1 = dx - image.spriteImage->getWidth() / 2.0f;
float x2 = x1 + image.spriteImage->getWidth();
float y1 = dy - image.spriteImage->getHeight() / 2.0f;
diff --git a/src/mbgl/text/shaping.hpp b/src/mbgl/text/shaping.hpp
index cd5e8105fd..30375179b6 100644
--- a/src/mbgl/text/shaping.hpp
+++ b/src/mbgl/text/shaping.hpp
@@ -3,15 +3,12 @@
#include <mbgl/text/glyph.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/sprite/sprite_image.hpp>
+#include <mbgl/style/layers/symbol_layer_properties.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
-struct SpriteAtlasElement;
-
-namespace style {
-class SymbolLayoutProperties;
-} // namespace style
+class SpriteAtlasElement;
class PositionedIcon {
public:
@@ -26,9 +23,9 @@ class PositionedIcon {
float left = 0;
float right = 0;
- operator bool() const { return image && (*image).pos.hasArea(); }
+ explicit operator bool() const { return image && (*image).pos.hasArea(); }
};
-PositionedIcon shapeIcon(const SpriteAtlasElement& image, const style::SymbolLayoutProperties&);
+PositionedIcon shapeIcon(const SpriteAtlasElement& image, const style::SymbolLayoutProperties::Evaluated&);
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index 84455e4787..9aeb35c821 100644
--- a/src/mbgl/tile/geometry_tile.cpp
+++ b/src/mbgl/tile/geometry_tile.cpp
@@ -6,6 +6,7 @@
#include <mbgl/style/layer_impl.hpp>
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/geometry/feature_index.hpp>
@@ -61,6 +62,12 @@ void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) {
return;
}
+ // Mark the tile as pending again if it was complete before to prevent signaling a complete
+ // state despite pending parse operations.
+ if (availableData == DataAvailability::All) {
+ availableData = DataAvailability::Some;
+ }
+
++correlationID;
requestedConfig = desiredConfig;
worker.invoke(&GeometryTileWorker::setPlacementConfig, desiredConfig, correlationID);
@@ -99,7 +106,7 @@ void GeometryTile::redoLayout() {
void GeometryTile::onLayout(LayoutResult result) {
availableData = DataAvailability::Some;
- buckets = std::move(result.buckets);
+ nonSymbolBuckets = std::move(result.nonSymbolBuckets);
featureIndex = std::move(result.featureIndex);
data = std::move(result.tileData);
observer->onTileChanged(*this);
@@ -109,10 +116,8 @@ void GeometryTile::onPlacement(PlacementResult result) {
if (result.correlationID == correlationID) {
availableData = DataAvailability::All;
}
- for (auto& bucket : result.buckets) {
- buckets[bucket.first] = std::move(bucket.second);
- }
- featureIndex->setCollisionTile(std::move(result.collisionTile));
+ symbolBuckets = std::move(result.symbolBuckets);
+ collisionTile = std::move(result.collisionTile);
observer->onTileChanged(*this);
}
@@ -122,7 +127,8 @@ void GeometryTile::onError(std::exception_ptr err) {
}
Bucket* GeometryTile::getBucket(const Layer& layer) {
- const auto it = buckets.find(layer.baseImpl->bucketName());
+ const auto& buckets = layer.is<SymbolLayer>() ? symbolBuckets : nonSymbolBuckets;
+ const auto it = buckets.find(layer.baseImpl->id);
if (it == buckets.end()) {
return nullptr;
}
@@ -147,7 +153,8 @@ void GeometryTile::queryRenderedFeatures(
layerIDs,
*data,
id.canonical,
- style);
+ style,
+ collisionTile.get());
}
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp
index 86243e8a09..c61a510311 100644
--- a/src/mbgl/tile/geometry_tile.hpp
+++ b/src/mbgl/tile/geometry_tile.hpp
@@ -50,7 +50,7 @@ public:
class LayoutResult {
public:
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> nonSymbolBuckets;
std::unique_ptr<FeatureIndex> featureIndex;
std::unique_ptr<GeometryTileData> tileData;
uint64_t correlationID;
@@ -59,7 +59,7 @@ public:
class PlacementResult {
public:
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets;
std::unique_ptr<CollisionTile> collisionTile;
uint64_t correlationID;
};
@@ -80,9 +80,12 @@ private:
uint64_t correlationID = 0;
optional<PlacementConfig> requestedConfig;
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> nonSymbolBuckets;
std::unique_ptr<FeatureIndex> featureIndex;
std::unique_ptr<const GeometryTileData> data;
+
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets;
+ std::unique_ptr<CollisionTile> collisionTile;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp
index abb3894d34..2a86b7feda 100644
--- a/src/mbgl/tile/geometry_tile_worker.cpp
+++ b/src/mbgl/tile/geometry_tile_worker.cpp
@@ -5,10 +5,11 @@
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/layout/symbol_layout.hpp>
#include <mbgl/style/bucket_parameters.hpp>
+#include <mbgl/style/group_by_layout.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/renderer/symbol_bucket.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/exception.hpp>
@@ -201,58 +202,64 @@ void GeometryTileWorker::redoLayout() {
return;
}
- // We're doing a fresh parse of the tile, because the underlying data or style has changed.
- symbolLayouts.clear();
+ std::vector<std::string> symbolOrder;
+ for (auto it = layers->rbegin(); it != layers->rend(); it++) {
+ if ((*it)->is<SymbolLayer>()) {
+ symbolOrder.push_back((*it)->getID());
+ }
+ }
- // We're storing a set of bucket names we've parsed to avoid parsing a bucket twice that is
- // referenced from more than one layer
- std::unordered_set<std::string> parsed;
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+ std::unordered_map<std::string, std::unique_ptr<SymbolLayout>> symbolLayoutMap;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
auto featureIndex = std::make_unique<FeatureIndex>();
+ BucketParameters parameters { id, obsolete, *featureIndex, mode };
- for (auto i = layers->rbegin(); i != layers->rend(); i++) {
+ std::vector<std::vector<const Layer*>> groups = groupByLayout(*layers);
+ for (auto& group : groups) {
if (obsolete) {
return;
}
- const Layer* layer = i->get();
- const std::string& bucketName = layer->baseImpl->bucketName();
-
- featureIndex->addBucketLayerName(bucketName, layer->baseImpl->id);
-
- if (parsed.find(bucketName) != parsed.end()) {
- continue;
- }
-
- parsed.emplace(bucketName);
-
if (!*data) {
continue; // Tile has no data.
}
- auto geometryLayer = (*data)->getLayer(layer->baseImpl->sourceLayer);
+ const Layer& leader = *group.at(0);
+
+ auto geometryLayer = (*data)->getLayer(leader.baseImpl->sourceLayer);
if (!geometryLayer) {
continue;
}
- BucketParameters parameters(id,
- *geometryLayer,
- obsolete,
- reinterpret_cast<uintptr_t>(this),
- glyphAtlas,
- *featureIndex,
- mode);
+ std::vector<std::string> layerIDs;
+ for (const auto& layer : group) {
+ layerIDs.push_back(layer->getID());
+ }
+
+ featureIndex->setBucketLayerIDs(leader.getID(), layerIDs);
- if (layer->is<SymbolLayer>()) {
- symbolLayouts.push_back(layer->as<SymbolLayer>()->impl->createLayout(parameters));
+ if (leader.is<SymbolLayer>()) {
+ symbolLayoutMap.emplace(leader.getID(),
+ leader.as<SymbolLayer>()->impl->createLayout(parameters, *geometryLayer, layerIDs));
} else {
- std::unique_ptr<Bucket> bucket = layer->baseImpl->createBucket(parameters);
- if (bucket->hasData()) {
- buckets.emplace(layer->baseImpl->bucketName(), std::move(bucket));
+ std::shared_ptr<Bucket> bucket = leader.baseImpl->createBucket(parameters, *geometryLayer);
+ if (!bucket->hasData()) {
+ continue;
+ }
+ for (const auto& layer : group) {
+ buckets.emplace(layer->getID(), bucket);
}
}
}
+ symbolLayouts.clear();
+ for (const auto& symbolLayerID : symbolOrder) {
+ auto it = symbolLayoutMap.find(symbolLayerID);
+ if (it != symbolLayoutMap.end()) {
+ symbolLayouts.push_back(std::move(it->second));
+ }
+ }
+
parent.invoke(&GeometryTile::onLayout, GeometryTile::LayoutResult {
std::move(buckets),
std::move(featureIndex),
@@ -304,7 +311,7 @@ void GeometryTileWorker::attemptPlacement() {
}
auto collisionTile = std::make_unique<CollisionTile>(*placementConfig);
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
for (auto& symbolLayout : symbolLayouts) {
if (obsolete) {
@@ -312,9 +319,13 @@ void GeometryTileWorker::attemptPlacement() {
}
symbolLayout->state = SymbolLayout::Placed;
- if (symbolLayout->hasSymbolInstances()) {
- buckets.emplace(symbolLayout->bucketName,
- symbolLayout->place(*collisionTile));
+ if (!symbolLayout->hasSymbolInstances()) {
+ continue;
+ }
+
+ std::shared_ptr<Bucket> bucket = symbolLayout->place(*collisionTile);
+ for (const auto& layerID : symbolLayout->layerIDs) {
+ buckets.emplace(layerID, bucket);
}
}
diff --git a/src/mbgl/tile/raster_tile_worker.cpp b/src/mbgl/tile/raster_tile_worker.cpp
index 443ee10400..219e9a2e41 100644
--- a/src/mbgl/tile/raster_tile_worker.cpp
+++ b/src/mbgl/tile/raster_tile_worker.cpp
@@ -2,6 +2,7 @@
#include <mbgl/tile/raster_tile.hpp>
#include <mbgl/renderer/raster_bucket.cpp>
#include <mbgl/actor/actor.hpp>
+#include <mbgl/util/premultiply.hpp>
namespace mbgl {
@@ -16,7 +17,7 @@ void RasterTileWorker::parse(std::shared_ptr<const std::string> data) {
}
try {
- auto bucket = std::make_unique<RasterBucket>(decodeImage(*data));
+ auto bucket = std::make_unique<RasterBucket>(util::unpremultiply(decodeImage(*data)));
parent.invoke(&RasterTile::onParsed, std::move(bucket));
} catch (...) {
parent.invoke(&RasterTile::onError, std::current_exception());
diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp
index 1375263107..e84eaaf780 100644
--- a/src/mbgl/tile/tile.cpp
+++ b/src/mbgl/tile/tile.cpp
@@ -2,7 +2,7 @@
#include <mbgl/tile/tile_observer.hpp>
#include <mbgl/renderer/debug_bucket.hpp>
#include <mbgl/util/string.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
namespace mbgl {
diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp
index eea89bd634..cebf913f56 100644
--- a/src/mbgl/tile/tile.hpp
+++ b/src/mbgl/tile/tile.hpp
@@ -75,9 +75,6 @@ public:
bool isComplete() const {
return availableData == DataAvailability::All;
}
- bool isIncomplete() const {
- return availableData == DataAvailability::Some;
- }
void dumpDebugLogs() const;
diff --git a/src/mbgl/util/color.cpp b/src/mbgl/util/color.cpp
index eea897d3ab..d5751b405f 100644
--- a/src/mbgl/util/color.cpp
+++ b/src/mbgl/util/color.cpp
@@ -1,4 +1,5 @@
#include <mbgl/util/color.hpp>
+#include <mbgl/util/string.hpp>
#include <csscolorparser/csscolorparser.hpp>
@@ -17,4 +18,12 @@ optional<Color> Color::parse(const std::string& s) {
}};
}
+std::string Color::stringify() const {
+ return "rgba(" +
+ util::toString(r * 255) + "," +
+ util::toString(g * 255) + "," +
+ util::toString(b * 255) + "," +
+ util::toString(a) + ")";
+}
+
} // namespace mbgl
diff --git a/src/mbgl/platform/event.cpp b/src/mbgl/util/event.cpp
index 68d75a2941..3a3be20f5c 100644
--- a/src/mbgl/platform/event.cpp
+++ b/src/mbgl/util/event.cpp
@@ -1,4 +1,4 @@
-#include <mbgl/platform/event.hpp>
+#include <mbgl/util/event.hpp>
#include <mbgl/util/enum.hpp>
namespace mbgl {
diff --git a/src/mbgl/util/i18n.cpp b/src/mbgl/util/i18n.cpp
new file mode 100644
index 0000000000..33ce5e22de
--- /dev/null
+++ b/src/mbgl/util/i18n.cpp
@@ -0,0 +1,357 @@
+#include "i18n.hpp"
+
+namespace {
+
+/** Defines a function that returns true if a codepoint is in a named block.
+ @param name The name of the block in CamelCase.
+ @param first The first codepoint in the block, inclusive.
+ @param last The last codepoint in the block, inclusive.
+ */
+#define DEFINE_IS_IN_UNICODE_BLOCK(name, first, last) \
+ inline bool isIn##name(uint16_t codepoint) { \
+ return codepoint >= first && codepoint <= last; \
+ }
+
+// The following table comes from <http://www.unicode.org/Public/9.0.0/ucd/Blocks.txt>.
+// Keep it synchronized with <http://www.unicode.org/Public/UCD/latest/ucd/Blocks.txt>.
+
+// DEFINE_IS_IN_UNICODE_BLOCK(BasicLatin, 0x0000, 0x007F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Latin1Supplement, 0x0080, 0x00FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(LatinExtendedA, 0x0100, 0x017F)
+// DEFINE_IS_IN_UNICODE_BLOCK(LatinExtendedB, 0x0180, 0x024F)
+// DEFINE_IS_IN_UNICODE_BLOCK(IPAExtensions, 0x0250, 0x02AF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SpacingModifierLetters, 0x02B0, 0x02FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(CombiningDiacriticalMarks, 0x0300, 0x036F)
+// DEFINE_IS_IN_UNICODE_BLOCK(GreekandCoptic, 0x0370, 0x03FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Cyrillic, 0x0400, 0x04FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(CyrillicSupplement, 0x0500, 0x052F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Armenian, 0x0530, 0x058F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Hebrew, 0x0590, 0x05FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Arabic, 0x0600, 0x06FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Syriac, 0x0700, 0x074F)
+// DEFINE_IS_IN_UNICODE_BLOCK(ArabicSupplement, 0x0750, 0x077F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Thaana, 0x0780, 0x07BF)
+// DEFINE_IS_IN_UNICODE_BLOCK(NKo, 0x07C0, 0x07FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Samaritan, 0x0800, 0x083F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Mandaic, 0x0840, 0x085F)
+// DEFINE_IS_IN_UNICODE_BLOCK(ArabicExtendedA, 0x08A0, 0x08FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Devanagari, 0x0900, 0x097F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Bengali, 0x0980, 0x09FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Gurmukhi, 0x0A00, 0x0A7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Gujarati, 0x0A80, 0x0AFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Oriya, 0x0B00, 0x0B7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Tamil, 0x0B80, 0x0BFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Telugu, 0x0C00, 0x0C7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Kannada, 0x0C80, 0x0CFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Malayalam, 0x0D00, 0x0D7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Sinhala, 0x0D80, 0x0DFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Thai, 0x0E00, 0x0E7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Lao, 0x0E80, 0x0EFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Tibetan, 0x0F00, 0x0FFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Myanmar, 0x1000, 0x109F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Georgian, 0x10A0, 0x10FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(HangulJamo, 0x1100, 0x11FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Ethiopic, 0x1200, 0x137F)
+// DEFINE_IS_IN_UNICODE_BLOCK(EthiopicSupplement, 0x1380, 0x139F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Cherokee, 0x13A0, 0x13FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(UnifiedCanadianAboriginalSyllabics, 0x1400, 0x167F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Ogham, 0x1680, 0x169F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Runic, 0x16A0, 0x16FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Tagalog, 0x1700, 0x171F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Hanunoo, 0x1720, 0x173F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Buhid, 0x1740, 0x175F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Tagbanwa, 0x1760, 0x177F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Khmer, 0x1780, 0x17FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Mongolian, 0x1800, 0x18AF)
+// DEFINE_IS_IN_UNICODE_BLOCK(UnifiedCanadianAboriginalSyllabicsExtended, 0x18B0, 0x18FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Limbu, 0x1900, 0x194F)
+// DEFINE_IS_IN_UNICODE_BLOCK(TaiLe, 0x1950, 0x197F)
+// DEFINE_IS_IN_UNICODE_BLOCK(NewTaiLue, 0x1980, 0x19DF)
+// DEFINE_IS_IN_UNICODE_BLOCK(KhmerSymbols, 0x19E0, 0x19FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Buginese, 0x1A00, 0x1A1F)
+// DEFINE_IS_IN_UNICODE_BLOCK(TaiTham, 0x1A20, 0x1AAF)
+// DEFINE_IS_IN_UNICODE_BLOCK(CombiningDiacriticalMarksExtended, 0x1AB0, 0x1AFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Balinese, 0x1B00, 0x1B7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Sundanese, 0x1B80, 0x1BBF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Batak, 0x1BC0, 0x1BFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Lepcha, 0x1C00, 0x1C4F)
+// DEFINE_IS_IN_UNICODE_BLOCK(OlChiki, 0x1C50, 0x1C7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(CyrillicExtendedC, 0x1C80, 0x1C8F)
+// DEFINE_IS_IN_UNICODE_BLOCK(SundaneseSupplement, 0x1CC0, 0x1CCF)
+// DEFINE_IS_IN_UNICODE_BLOCK(VedicExtensions, 0x1CD0, 0x1CFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(PhoneticExtensions, 0x1D00, 0x1D7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(PhoneticExtensionsSupplement, 0x1D80, 0x1DBF)
+// DEFINE_IS_IN_UNICODE_BLOCK(CombiningDiacriticalMarksSupplement, 0x1DC0, 0x1DFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(LatinExtendedAdditional, 0x1E00, 0x1EFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(GreekExtended, 0x1F00, 0x1FFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(GeneralPunctuation, 0x2000, 0x206F)
+// DEFINE_IS_IN_UNICODE_BLOCK(SuperscriptsandSubscripts, 0x2070, 0x209F)
+// DEFINE_IS_IN_UNICODE_BLOCK(CurrencySymbols, 0x20A0, 0x20CF)
+// DEFINE_IS_IN_UNICODE_BLOCK(CombiningDiacriticalMarksforSymbols, 0x20D0, 0x20FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(LetterlikeSymbols, 0x2100, 0x214F)
+// DEFINE_IS_IN_UNICODE_BLOCK(NumberForms, 0x2150, 0x218F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Arrows, 0x2190, 0x21FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(MathematicalOperators, 0x2200, 0x22FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(MiscellaneousTechnical, 0x2300, 0x23FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(ControlPictures, 0x2400, 0x243F)
+// DEFINE_IS_IN_UNICODE_BLOCK(OpticalCharacterRecognition, 0x2440, 0x245F)
+// DEFINE_IS_IN_UNICODE_BLOCK(EnclosedAlphanumerics, 0x2460, 0x24FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(BoxDrawing, 0x2500, 0x257F)
+// DEFINE_IS_IN_UNICODE_BLOCK(BlockElements, 0x2580, 0x259F)
+// DEFINE_IS_IN_UNICODE_BLOCK(GeometricShapes, 0x25A0, 0x25FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(MiscellaneousSymbols, 0x2600, 0x26FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Dingbats, 0x2700, 0x27BF)
+// DEFINE_IS_IN_UNICODE_BLOCK(MiscellaneousMathematicalSymbolsA, 0x27C0, 0x27EF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SupplementalArrowsA, 0x27F0, 0x27FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(BraillePatterns, 0x2800, 0x28FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SupplementalArrowsB, 0x2900, 0x297F)
+// DEFINE_IS_IN_UNICODE_BLOCK(MiscellaneousMathematicalSymbolsB, 0x2980, 0x29FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SupplementalMathematicalOperators, 0x2A00, 0x2AFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(MiscellaneousSymbolsandArrows, 0x2B00, 0x2BFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Glagolitic, 0x2C00, 0x2C5F)
+// DEFINE_IS_IN_UNICODE_BLOCK(LatinExtendedC, 0x2C60, 0x2C7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Coptic, 0x2C80, 0x2CFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(GeorgianSupplement, 0x2D00, 0x2D2F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Tifinagh, 0x2D30, 0x2D7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(EthiopicExtended, 0x2D80, 0x2DDF)
+// DEFINE_IS_IN_UNICODE_BLOCK(CyrillicExtendedA, 0x2DE0, 0x2DFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SupplementalPunctuation, 0x2E00, 0x2E7F)
+DEFINE_IS_IN_UNICODE_BLOCK(CJKRadicalsSupplement, 0x2E80, 0x2EFF)
+DEFINE_IS_IN_UNICODE_BLOCK(KangxiRadicals, 0x2F00, 0x2FDF)
+DEFINE_IS_IN_UNICODE_BLOCK(IdeographicDescriptionCharacters, 0x2FF0, 0x2FFF)
+DEFINE_IS_IN_UNICODE_BLOCK(CJKSymbolsandPunctuation, 0x3000, 0x303F)
+DEFINE_IS_IN_UNICODE_BLOCK(Hiragana, 0x3040, 0x309F)
+DEFINE_IS_IN_UNICODE_BLOCK(Katakana, 0x30A0, 0x30FF)
+DEFINE_IS_IN_UNICODE_BLOCK(Bopomofo, 0x3100, 0x312F)
+// DEFINE_IS_IN_UNICODE_BLOCK(HangulCompatibilityJamo, 0x3130, 0x318F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Kanbun, 0x3190, 0x319F)
+DEFINE_IS_IN_UNICODE_BLOCK(BopomofoExtended, 0x31A0, 0x31BF)
+DEFINE_IS_IN_UNICODE_BLOCK(CJKStrokes, 0x31C0, 0x31EF)
+DEFINE_IS_IN_UNICODE_BLOCK(KatakanaPhoneticExtensions, 0x31F0, 0x31FF)
+DEFINE_IS_IN_UNICODE_BLOCK(EnclosedCJKLettersandMonths, 0x3200, 0x32FF)
+DEFINE_IS_IN_UNICODE_BLOCK(CJKCompatibility, 0x3300, 0x33FF)
+DEFINE_IS_IN_UNICODE_BLOCK(CJKUnifiedIdeographsExtensionA, 0x3400, 0x4DBF)
+// DEFINE_IS_IN_UNICODE_BLOCK(YijingHexagramSymbols, 0x4DC0, 0x4DFF)
+DEFINE_IS_IN_UNICODE_BLOCK(CJKUnifiedIdeographs, 0x4E00, 0x9FFF)
+DEFINE_IS_IN_UNICODE_BLOCK(YiSyllables, 0xA000, 0xA48F)
+DEFINE_IS_IN_UNICODE_BLOCK(YiRadicals, 0xA490, 0xA4CF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Lisu, 0xA4D0, 0xA4FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Vai, 0xA500, 0xA63F)
+// DEFINE_IS_IN_UNICODE_BLOCK(CyrillicExtendedB, 0xA640, 0xA69F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Bamum, 0xA6A0, 0xA6FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(ModifierToneLetters, 0xA700, 0xA71F)
+// DEFINE_IS_IN_UNICODE_BLOCK(LatinExtendedD, 0xA720, 0xA7FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SylotiNagri, 0xA800, 0xA82F)
+// DEFINE_IS_IN_UNICODE_BLOCK(CommonIndicNumberForms, 0xA830, 0xA83F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Phagspa, 0xA840, 0xA87F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Saurashtra, 0xA880, 0xA8DF)
+// DEFINE_IS_IN_UNICODE_BLOCK(DevanagariExtended, 0xA8E0, 0xA8FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(KayahLi, 0xA900, 0xA92F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Rejang, 0xA930, 0xA95F)
+// DEFINE_IS_IN_UNICODE_BLOCK(HangulJamoExtendedA, 0xA960, 0xA97F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Javanese, 0xA980, 0xA9DF)
+// DEFINE_IS_IN_UNICODE_BLOCK(MyanmarExtendedB, 0xA9E0, 0xA9FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Cham, 0xAA00, 0xAA5F)
+// DEFINE_IS_IN_UNICODE_BLOCK(MyanmarExtendedA, 0xAA60, 0xAA7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(TaiViet, 0xAA80, 0xAADF)
+// DEFINE_IS_IN_UNICODE_BLOCK(MeeteiMayekExtensions, 0xAAE0, 0xAAFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(EthiopicExtendedA, 0xAB00, 0xAB2F)
+// DEFINE_IS_IN_UNICODE_BLOCK(LatinExtendedE, 0xAB30, 0xAB6F)
+// DEFINE_IS_IN_UNICODE_BLOCK(CherokeeSupplement, 0xAB70, 0xABBF)
+// DEFINE_IS_IN_UNICODE_BLOCK(MeeteiMayek, 0xABC0, 0xABFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(HangulSyllables, 0xAC00, 0xD7AF)
+// DEFINE_IS_IN_UNICODE_BLOCK(HangulJamoExtendedB, 0xD7B0, 0xD7FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(HighSurrogates, 0xD800, 0xDB7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(HighPrivateUseSurrogates, 0xDB80, 0xDBFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(LowSurrogates, 0xDC00, 0xDFFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(PrivateUseArea, 0xE000, 0xF8FF)
+DEFINE_IS_IN_UNICODE_BLOCK(CJKCompatibilityIdeographs, 0xF900, 0xFAFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(AlphabeticPresentationForms, 0xFB00, 0xFB4F)
+// DEFINE_IS_IN_UNICODE_BLOCK(ArabicPresentationFormsA, 0xFB50, 0xFDFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(VariationSelectors, 0xFE00, 0xFE0F)
+DEFINE_IS_IN_UNICODE_BLOCK(VerticalForms, 0xFE10, 0xFE1F)
+// DEFINE_IS_IN_UNICODE_BLOCK(CombiningHalfMarks, 0xFE20, 0xFE2F)
+DEFINE_IS_IN_UNICODE_BLOCK(CJKCompatibilityForms, 0xFE30, 0xFE4F)
+// DEFINE_IS_IN_UNICODE_BLOCK(SmallFormVariants, 0xFE50, 0xFE6F)
+// DEFINE_IS_IN_UNICODE_BLOCK(ArabicPresentationFormsB, 0xFE70, 0xFEFF)
+DEFINE_IS_IN_UNICODE_BLOCK(HalfwidthandFullwidthForms, 0xFF00, 0xFFEF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Specials, 0xFFF0, 0xFFFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(LinearBSyllabary, 0x10000, 0x1007F)
+// DEFINE_IS_IN_UNICODE_BLOCK(LinearBIdeograms, 0x10080, 0x100FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(AegeanNumbers, 0x10100, 0x1013F)
+// DEFINE_IS_IN_UNICODE_BLOCK(AncientGreekNumbers, 0x10140, 0x1018F)
+// DEFINE_IS_IN_UNICODE_BLOCK(AncientSymbols, 0x10190, 0x101CF)
+// DEFINE_IS_IN_UNICODE_BLOCK(PhaistosDisc, 0x101D0, 0x101FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Lycian, 0x10280, 0x1029F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Carian, 0x102A0, 0x102DF)
+// DEFINE_IS_IN_UNICODE_BLOCK(CopticEpactNumbers, 0x102E0, 0x102FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(OldItalic, 0x10300, 0x1032F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Gothic, 0x10330, 0x1034F)
+// DEFINE_IS_IN_UNICODE_BLOCK(OldPermic, 0x10350, 0x1037F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Ugaritic, 0x10380, 0x1039F)
+// DEFINE_IS_IN_UNICODE_BLOCK(OldPersian, 0x103A0, 0x103DF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Deseret, 0x10400, 0x1044F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Shavian, 0x10450, 0x1047F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Osmanya, 0x10480, 0x104AF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Osage, 0x104B0, 0x104FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Elbasan, 0x10500, 0x1052F)
+// DEFINE_IS_IN_UNICODE_BLOCK(CaucasianAlbanian, 0x10530, 0x1056F)
+// DEFINE_IS_IN_UNICODE_BLOCK(LinearA, 0x10600, 0x1077F)
+// DEFINE_IS_IN_UNICODE_BLOCK(CypriotSyllabary, 0x10800, 0x1083F)
+// DEFINE_IS_IN_UNICODE_BLOCK(ImperialAramaic, 0x10840, 0x1085F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Palmyrene, 0x10860, 0x1087F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Nabataean, 0x10880, 0x108AF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Hatran, 0x108E0, 0x108FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Phoenician, 0x10900, 0x1091F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Lydian, 0x10920, 0x1093F)
+// DEFINE_IS_IN_UNICODE_BLOCK(MeroiticHieroglyphs, 0x10980, 0x1099F)
+// DEFINE_IS_IN_UNICODE_BLOCK(MeroiticCursive, 0x109A0, 0x109FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Kharoshthi, 0x10A00, 0x10A5F)
+// DEFINE_IS_IN_UNICODE_BLOCK(OldSouthArabian, 0x10A60, 0x10A7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(OldNorthArabian, 0x10A80, 0x10A9F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Manichaean, 0x10AC0, 0x10AFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Avestan, 0x10B00, 0x10B3F)
+// DEFINE_IS_IN_UNICODE_BLOCK(InscriptionalParthian, 0x10B40, 0x10B5F)
+// DEFINE_IS_IN_UNICODE_BLOCK(InscriptionalPahlavi, 0x10B60, 0x10B7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(PsalterPahlavi, 0x10B80, 0x10BAF)
+// DEFINE_IS_IN_UNICODE_BLOCK(OldTurkic, 0x10C00, 0x10C4F)
+// DEFINE_IS_IN_UNICODE_BLOCK(OldHungarian, 0x10C80, 0x10CFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(RumiNumeralSymbols, 0x10E60, 0x10E7F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Brahmi, 0x11000, 0x1107F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Kaithi, 0x11080, 0x110CF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SoraSompeng, 0x110D0, 0x110FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Chakma, 0x11100, 0x1114F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Mahajani, 0x11150, 0x1117F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Sharada, 0x11180, 0x111DF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SinhalaArchaicNumbers, 0x111E0, 0x111FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Khojki, 0x11200, 0x1124F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Multani, 0x11280, 0x112AF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Khudawadi, 0x112B0, 0x112FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Grantha, 0x11300, 0x1137F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Newa, 0x11400, 0x1147F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Tirhuta, 0x11480, 0x114DF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Siddham, 0x11580, 0x115FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Modi, 0x11600, 0x1165F)
+// DEFINE_IS_IN_UNICODE_BLOCK(MongolianSupplement, 0x11660, 0x1167F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Takri, 0x11680, 0x116CF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Ahom, 0x11700, 0x1173F)
+// DEFINE_IS_IN_UNICODE_BLOCK(WarangCiti, 0x118A0, 0x118FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(PauCinHau, 0x11AC0, 0x11AFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Bhaiksuki, 0x11C00, 0x11C6F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Marchen, 0x11C70, 0x11CBF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Cuneiform, 0x12000, 0x123FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(CuneiformNumbersandPunctuation, 0x12400, 0x1247F)
+// DEFINE_IS_IN_UNICODE_BLOCK(EarlyDynasticCuneiform, 0x12480, 0x1254F)
+// DEFINE_IS_IN_UNICODE_BLOCK(EgyptianHieroglyphs, 0x13000, 0x1342F)
+// DEFINE_IS_IN_UNICODE_BLOCK(AnatolianHieroglyphs, 0x14400, 0x1467F)
+// DEFINE_IS_IN_UNICODE_BLOCK(BamumSupplement, 0x16800, 0x16A3F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Mro, 0x16A40, 0x16A6F)
+// DEFINE_IS_IN_UNICODE_BLOCK(BassaVah, 0x16AD0, 0x16AFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(PahawhHmong, 0x16B00, 0x16B8F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Miao, 0x16F00, 0x16F9F)
+// DEFINE_IS_IN_UNICODE_BLOCK(IdeographicSymbolsandPunctuation, 0x16FE0, 0x16FFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Tangut, 0x17000, 0x187FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(TangutComponents, 0x18800, 0x18AFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(KanaSupplement, 0x1B000, 0x1B0FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Duployan, 0x1BC00, 0x1BC9F)
+// DEFINE_IS_IN_UNICODE_BLOCK(ShorthandFormatControls, 0x1BCA0, 0x1BCAF)
+// DEFINE_IS_IN_UNICODE_BLOCK(ByzantineMusicalSymbols, 0x1D000, 0x1D0FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(MusicalSymbols, 0x1D100, 0x1D1FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(AncientGreekMusicalNotation, 0x1D200, 0x1D24F)
+// DEFINE_IS_IN_UNICODE_BLOCK(TaiXuanJingSymbols, 0x1D300, 0x1D35F)
+// DEFINE_IS_IN_UNICODE_BLOCK(CountingRodNumerals, 0x1D360, 0x1D37F)
+// DEFINE_IS_IN_UNICODE_BLOCK(MathematicalAlphanumericSymbols, 0x1D400, 0x1D7FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SuttonSignWriting, 0x1D800, 0x1DAAF)
+// DEFINE_IS_IN_UNICODE_BLOCK(GlagoliticSupplement, 0x1E000, 0x1E02F)
+// DEFINE_IS_IN_UNICODE_BLOCK(MendeKikakui, 0x1E800, 0x1E8DF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Adlam, 0x1E900, 0x1E95F)
+// DEFINE_IS_IN_UNICODE_BLOCK(ArabicMathematicalAlphabeticSymbols, 0x1EE00, 0x1EEFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(MahjongTiles, 0x1F000, 0x1F02F)
+// DEFINE_IS_IN_UNICODE_BLOCK(DominoTiles, 0x1F030, 0x1F09F)
+// DEFINE_IS_IN_UNICODE_BLOCK(PlayingCards, 0x1F0A0, 0x1F0FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(EnclosedAlphanumericSupplement, 0x1F100, 0x1F1FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(EnclosedIdeographicSupplement, 0x1F200, 0x1F2FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(MiscellaneousSymbolsandPictographs, 0x1F300, 0x1F5FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(Emoticons, 0x1F600, 0x1F64F)
+// DEFINE_IS_IN_UNICODE_BLOCK(OrnamentalDingbats, 0x1F650, 0x1F67F)
+// DEFINE_IS_IN_UNICODE_BLOCK(TransportandMapSymbols, 0x1F680, 0x1F6FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(AlchemicalSymbols, 0x1F700, 0x1F77F)
+// DEFINE_IS_IN_UNICODE_BLOCK(GeometricShapesExtended, 0x1F780, 0x1F7FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SupplementalArrowsC, 0x1F800, 0x1F8FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SupplementalSymbolsandPictographs, 0x1F900, 0x1F9FF)
+// DEFINE_IS_IN_UNICODE_BLOCK(CJKUnifiedIdeographsExtensionB, 0x20000, 0x2A6DF)
+// DEFINE_IS_IN_UNICODE_BLOCK(CJKUnifiedIdeographsExtensionC, 0x2A700, 0x2B73F)
+// DEFINE_IS_IN_UNICODE_BLOCK(CJKUnifiedIdeographsExtensionD, 0x2B740, 0x2B81F)
+// DEFINE_IS_IN_UNICODE_BLOCK(CJKUnifiedIdeographsExtensionE, 0x2B820, 0x2CEAF)
+// DEFINE_IS_IN_UNICODE_BLOCK(CJKCompatibilityIdeographsSupplement, 0x2F800, 0x2FA1F)
+// DEFINE_IS_IN_UNICODE_BLOCK(Tags, 0xE0000, 0xE007F)
+// DEFINE_IS_IN_UNICODE_BLOCK(VariationSelectorsSupplement, 0xE0100, 0xE01EF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SupplementaryPrivateUseAreaA, 0xF0000, 0xFFFFF)
+// DEFINE_IS_IN_UNICODE_BLOCK(SupplementaryPrivateUseAreaB, 0x100000, 0x10FFFF)
+}
+
+namespace mbgl {
+namespace util {
+namespace i18n {
+
+bool allowsWordBreaking(uint16_t chr) {
+ return (chr == 0x0a /* newline */
+ || chr == 0x20 /* space */
+ || chr == 0x26 /* ampersand */
+ || chr == 0x28 /* open parenthesis */
+ || chr == 0x29 /* close parenthesis */
+ || chr == 0x2b /* plus sign */
+ || chr == 0x2d /* hyphen-minus */
+ || chr == 0x2f /* solidus */
+ || chr == 0xad /* soft hyphen */
+ || chr == 0xb7 /* middle dot */
+ || chr == 0x200b /* zero-width space */
+ || chr == 0x2010 /* hyphen */
+ || chr == 0x2013 /* en dash */);
+}
+
+bool allowsIdeographicBreaking(const std::u16string& string) {
+ for (uint16_t chr : string) {
+ if (!allowsIdeographicBreaking(chr)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool allowsIdeographicBreaking(uint16_t chr) {
+ // Allow U+2027 "Interpunct" for hyphenation of Chinese words
+ if (chr == 0x2027)
+ return true;
+
+ // Return early for characters outside all ideographic ranges.
+ if (chr < 0x2E80)
+ return false;
+
+ return (isInBopomofo(chr) || isInBopomofoExtended(chr) || isInCJKCompatibility(chr) ||
+ isInCJKCompatibilityForms(chr) || isInCJKCompatibilityIdeographs(chr) ||
+ isInCJKRadicalsSupplement(chr) || isInCJKStrokes(chr) ||
+ isInCJKSymbolsandPunctuation(chr) || isInCJKUnifiedIdeographs(chr) ||
+ isInCJKUnifiedIdeographsExtensionA(chr) || isInEnclosedCJKLettersandMonths(chr) ||
+ isInHalfwidthandFullwidthForms(chr) || isInHiragana(chr) ||
+ isInIdeographicDescriptionCharacters(chr) || isInKangxiRadicals(chr) ||
+ isInKatakana(chr) || isInKatakanaPhoneticExtensions(chr) || isInVerticalForms(chr) ||
+ isInYiRadicals(chr) || isInYiSyllables(chr));
+
+ // The following blocks also allow ideographic breaking; however, for other
+ // reasons, Mapbox GL lacks support for codepoints beyond U+FFFF.
+ // https://github.com/mapbox/mapbox-gl/issues/29
+ // return (isInTangut(chr)
+ // || isInTangutComponents(chr)
+ // || isInIdeographicSymbolsandPunctuation(chr)
+ // || isInEnclosedIdeographicSupplement(chr)
+ // || isInCJKUnifiedIdeographsExtensionB(chr)
+ // || isInCJKUnifiedIdeographsExtensionC(chr)
+ // || isInCJKUnifiedIdeographsExtensionD(chr)
+ // || isInCJKUnifiedIdeographsExtensionE(chr)
+ // || isInCJKCompatibilityIdeographsSupplement(chr));
+}
+
+} // namespace i18n
+} // namespace util
+} // namespace mbgl
diff --git a/src/mbgl/util/i18n.hpp b/src/mbgl/util/i18n.hpp
new file mode 100644
index 0000000000..f1d3f53f72
--- /dev/null
+++ b/src/mbgl/util/i18n.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <string>
+
+namespace mbgl {
+namespace util {
+namespace i18n {
+
+/** Returns whether a line break can be inserted after the character indicated
+ by the given Unicode codepoint due to word breaking. */
+bool allowsWordBreaking(uint16_t chr);
+
+/** Returns whether a line break can be inserted after any character in the
+ given string. If false, line breaking should occur on word boundaries
+ instead. */
+bool allowsIdeographicBreaking(const std::u16string& string);
+
+/** Returns whether a line break can be inserted after the character indicated
+ by the given Unicode codepoint due to ideographic breaking. */
+bool allowsIdeographicBreaking(uint16_t chr);
+
+} // namespace i18n
+} // namespace util
+} // namespace mbgl
diff --git a/src/mbgl/util/ignore.hpp b/src/mbgl/util/ignore.hpp
new file mode 100644
index 0000000000..955b1de2fa
--- /dev/null
+++ b/src/mbgl/util/ignore.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <initializer_list>
+
+namespace mbgl {
+namespace util {
+
+// Accept any number of parameters of any types, and do nothing with them.
+// Useful for providing a context for parameter pack expansion where a legal
+// expansion context is not otherwise available.
+//
+// See https://github.com/mapbox/cpp/blob/master/C%2B%2B%20Structural%20Metaprogramming.md
+// for more details.
+//
+template <class... Ts> void ignore(Ts&&...) {}
+
+// std::initializer_list overload, for situations where you need sequenced
+// modifications.
+//
+template <class T> void ignore(const std::initializer_list<T>&) {}
+
+} // namespace util
+} // namespace mbgl
diff --git a/src/mbgl/util/indexed_tuple.hpp b/src/mbgl/util/indexed_tuple.hpp
new file mode 100644
index 0000000000..110e7dce12
--- /dev/null
+++ b/src/mbgl/util/indexed_tuple.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <type_traits>
+#include <tuple>
+
+namespace mbgl {
+
+template <class T, class... Ts>
+struct TypeIndex;
+
+template <class T, class... Ts>
+struct TypeIndex<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};
+
+template <class T, class U, class... Ts>
+struct TypeIndex<T, U, Ts...> : std::integral_constant<std::size_t, 1 + TypeIndex<T, Ts...>::value> {};
+
+template <class...> class TypeList {};
+
+template <class...> class IndexedTuple;
+
+// A tuple of Ts, where individual members can be accessed via `t.get<I>()` for I ∈ Is.
+//
+// See https://github.com/mapbox/cpp/blob/master/C%2B%2B%20Structural%20Metaprogramming.md
+// for motivation.
+//
+template <class... Is, class... Ts>
+class IndexedTuple<TypeList<Is...>, TypeList<Ts...>> : public std::tuple<Ts...> {
+public:
+ static_assert(sizeof...(Is) == sizeof...(Ts), "IndexedTuple size mismatch");
+
+ using std::tuple<Ts...>::tuple;
+
+ template <class I>
+ static constexpr std::size_t Index = TypeIndex<I, Is...>::value;
+
+ template <class I>
+ auto& get() {
+ return std::get<Index<I>>(*this);
+ }
+
+ template <class I>
+ const auto& get() const {
+ return std::get<Index<I>>(*this);
+ }
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/util/interpolate.hpp b/src/mbgl/util/interpolate.hpp
index 958b185d5b..ef066377da 100644
--- a/src/mbgl/util/interpolate.hpp
+++ b/src/mbgl/util/interpolate.hpp
@@ -62,6 +62,10 @@ struct Uninterpolated {
}
};
+template <>
+struct Interpolator<bool>
+ : Uninterpolated {};
+
template <class T>
struct Interpolator<T, typename std::enable_if_t<std::is_enum<T>::value>>
: Uninterpolated {};
diff --git a/src/mbgl/platform/log.cpp b/src/mbgl/util/logging.cpp
index b140485dd6..939f1def64 100644
--- a/src/mbgl/platform/log.cpp
+++ b/src/mbgl/util/logging.cpp
@@ -1,4 +1,4 @@
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/enum.hpp>
#include <mbgl/util/thread.hpp>
diff --git a/src/mbgl/util/mapbox.cpp b/src/mbgl/util/mapbox.cpp
index 9cf250f7a3..642945ba07 100644
--- a/src/mbgl/util/mapbox.cpp
+++ b/src/mbgl/util/mapbox.cpp
@@ -1,11 +1,12 @@
#include <mbgl/util/mapbox.hpp>
#include <mbgl/util/constants.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
+#include <mbgl/util/url.hpp>
#include <stdexcept>
#include <vector>
#include <iostream>
-#include <regex>
+#include <cstring>
namespace {
@@ -22,184 +23,148 @@ bool isMapboxURL(const std::string& url) {
return url.compare(0, protocolLength, protocol) == 0;
}
-static std::vector<std::string> getMapboxURLPathname(const std::string& url) {
- std::vector<std::string> pathname;
- auto startIndex = protocolLength;
- auto end = url.find_first_of("?#");
- if (end == std::string::npos) {
- end = url.length();
- }
- while (startIndex < end) {
- auto endIndex = url.find("/", startIndex);
- if (endIndex == std::string::npos) {
- endIndex = end;
- }
- pathname.push_back(url.substr(startIndex, endIndex - startIndex));
- startIndex = endIndex + 1;
- }
- return pathname;
-}
-
-static std::pair<std::string, std::size_t> normalizeQuery(const std::string& url) {
- std::string query;
-
- auto queryIdx = url.find("?");
- if (queryIdx != std::string::npos) {
- query = url.substr(queryIdx + 1, url.length() - queryIdx + 1);
- if (!query.empty()) {
- query = "&" + query;
- }
- }
-
- return std::make_pair(query, queryIdx);
+static bool equals(const std::string& str, const URL::Segment& segment, const char* ref) {
+ return str.compare(segment.first, segment.second, ref) == 0;
}
-std::string normalizeSourceURL(const std::string& baseURL, const std::string& url, const std::string& accessToken) {
- if (!isMapboxURL(url)) {
- return url;
+std::string normalizeSourceURL(const std::string& baseURL,
+ const std::string& str,
+ const std::string& accessToken) {
+ if (!isMapboxURL(str)) {
+ return str;
}
-
if (accessToken.empty()) {
- throw std::runtime_error("You must provide a Mapbox API access token for Mapbox tile sources");
+ throw std::runtime_error(
+ "You must provide a Mapbox API access token for Mapbox tile sources");
}
- auto query = normalizeQuery(url);
- return baseURL + "/v4/" + url.substr(protocolLength, query.second - protocolLength) + ".json?access_token=" + accessToken + "&secure" + query.first;
+ const URL url(str);
+ const auto tpl = baseURL + "/v4/{domain}.json?access_token=" + accessToken + "&secure";
+ return transformURL(tpl, str, url);
}
-std::string normalizeStyleURL(const std::string& baseURL, const std::string& url, const std::string& accessToken) {
- if (!isMapboxURL(url)) {
- return url;
+std::string normalizeStyleURL(const std::string& baseURL,
+ const std::string& str,
+ const std::string& accessToken) {
+ if (!isMapboxURL(str)) {
+ return str;
}
- const auto pathname = getMapboxURLPathname(url);
- if (pathname.size() < 3) {
+ const URL url(str);
+ if (!equals(str, url.domain, "styles")) {
Log::Error(Event::ParseStyle, "Invalid style URL");
- return url;
+ return str;
}
- const auto& user = pathname[1];
- const auto& id = pathname[2];
- const bool isDraft = pathname.size() > 3;
- return baseURL + "/styles/v1/" + user + "/" + id + (isDraft ? "/draft" : "") + "?access_token=" + accessToken + normalizeQuery(url).first;
+ const auto tpl = baseURL + "/styles/v1/{path}?access_token=" + accessToken;
+ return transformURL(tpl, str, url);
}
-std::string normalizeSpriteURL(const std::string& baseURL, const std::string& url, const std::string& accessToken) {
- if (!isMapboxURL(url)) {
- return url;
+std::string normalizeSpriteURL(const std::string& baseURL,
+ const std::string& str,
+ const std::string& accessToken) {
+ if (!isMapboxURL(str)) {
+ return str;
}
- const auto pathname = getMapboxURLPathname(url);
- if (pathname.size() < 3) {
- Log::Error(Event::ParseStyle, "Invalid sprite URL");
- return url;
- }
-
- const auto& user = pathname[1];
- const bool isDraft = pathname.size() > 3;
-
- const auto& name = isDraft ? pathname[3] : pathname[2];
- const size_t index = name.find_first_of("@.");
- if (index == std::string::npos) {
+ const URL url(str);
+ if (!equals(str, url.domain, "sprites")) {
Log::Error(Event::ParseStyle, "Invalid sprite URL");
- return url;
+ return str;
}
- const auto& extension = name.substr(index);
- if (isDraft) {
- const auto& id = pathname[2];
- return baseURL + "/styles/v1/" + user + "/" + id + "/draft/sprite" + extension +
- "?access_token=" + accessToken;
-
- } else {
- const auto& id = pathname[2].substr(0, index);
- return baseURL + "/styles/v1/" + user + "/" + id + "/sprite" + extension + "?access_token=" +
- accessToken;
- }
+ const auto tpl =
+ baseURL + "/styles/v1/{directory}{filename}/sprite{extension}?access_token=" + accessToken;
+ return transformURL(tpl, str, url);
}
-std::string normalizeGlyphsURL(const std::string& baseURL, const std::string& url, const std::string& accessToken) {
- if (!isMapboxURL(url)) {
- return url;
+std::string normalizeGlyphsURL(const std::string& baseURL,
+ const std::string& str,
+ const std::string& accessToken) {
+ if (!isMapboxURL(str)) {
+ return str;
}
- const auto pathname = getMapboxURLPathname(url);
- if (pathname.size() < 4) {
- Log::Error(Event::ParseStyle, "Invalid glyph URL");
- return url;
+ const URL url(str);
+ if (!equals(str, url.domain, "fonts")) {
+ Log::Error(Event::ParseStyle, "Invalid glyph URL");
+ return str;
}
- const auto& user = pathname[1];
- const auto& fontstack = pathname[2];
- const auto& range = pathname[3];
-
- return baseURL + "/fonts/v1/" + user + "/" + fontstack + "/" + range + "?access_token=" + accessToken;
+ const auto tpl = baseURL + "/fonts/v1/{path}?access_token=" + accessToken;
+ return transformURL(tpl, str, url);
}
-std::string normalizeTileURL(const std::string& baseURL, const std::string& url, const std::string& accessToken) {
- if (!isMapboxURL(url)) {
- return url;
+std::string normalizeTileURL(const std::string& baseURL,
+ const std::string& str,
+ const std::string& accessToken) {
+ if (!isMapboxURL(str)) {
+ return str;
}
- auto query = normalizeQuery(url);
- return baseURL + "/v4/" + url.substr(sizeof("mapbox://tiles/") - 1, query.second - sizeof("mapbox://tiles/") + 1) + "?access_token=" + accessToken + normalizeQuery(url).first;
-}
-
-std::string canonicalizeTileURL(const std::string& url, SourceType type, uint16_t tileSize) {
- auto tilesetStartIdx = url.find("/v4/");
- if (tilesetStartIdx == std::string::npos) {
- return url;
+ const URL url(str);
+ if (!equals(str, url.domain, "tiles")) {
+ Log::Error(Event::ParseStyle, "Invalid tile URL");
+ return str;
}
- tilesetStartIdx += sizeof("/v4/") - 1;
+ const auto tpl = baseURL + "/v4/{path}?access_token=" + accessToken;
+ return transformURL(tpl, str, url);
+}
- const auto tilesetEndIdx = url.find("/", tilesetStartIdx);
- if (tilesetEndIdx == std::string::npos) {
- return url;
- }
+std::string
+canonicalizeTileURL(const std::string& str, const SourceType type, const uint16_t tileSize) {
+ const char* version = "v4/";
+ const size_t versionLen = strlen(version);
- auto queryIdx = url.rfind("?");
- if (queryIdx == std::string::npos) {
- queryIdx = url.length();
- }
+ const URL url(str);
+ const Path path(str, url.path.first, url.path.second);
- auto basenameIdx = url.rfind("/", queryIdx);
- if (basenameIdx == std::string::npos || basenameIdx == queryIdx - 1) {
- basenameIdx = url.length();
- } else {
- basenameIdx += 1;
+ // Make sure that we are dealing with a valid Mapbox tile URL.
+ // Has to be /v4/, with a valid filename + extension
+ if (str.compare(url.path.first, versionLen, version) != 0 || path.filename.second == 0 ||
+ path.extension.second <= 1) {
+ // Not a proper Mapbox tile URL.
+ return str;
}
- const auto extensionIdx = url.find(".", basenameIdx);
- if (extensionIdx == std::string::npos || extensionIdx == queryIdx - 1) {
- return url;
+ // Reassemble the canonical URL from the parts we've parsed before.
+ std::string result = "mapbox://tiles/";
+ result.append(str, path.directory.first + versionLen, path.directory.second - versionLen);
+ result.append(str, path.filename.first, path.filename.second);
+ if (type == SourceType::Raster) {
+ result += tileSize == util::tileSize ? "@2x" : "{ratio}";
}
- const auto tileset = url.substr(tilesetStartIdx, tilesetEndIdx - tilesetStartIdx);
- auto extension = url.substr(extensionIdx + 1, queryIdx - extensionIdx - 1);
-
#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(QT_IMAGE_DECODERS)
- // Replace PNG with WebP.
- if (extension == "png") {
- extension = "webp";
- }
+ const bool forceWebP = str.compare(path.extension.first, path.extension.second, ".png") == 0;
+#else
+ const bool forceWebP = false;
#endif // !defined(__ANDROID__) && !defined(__APPLE__) && !defined(QT_IMAGE_DECODERS)
- std::string result = "mapbox://tiles/" + tileset + "/{z}/{x}/{y}";
-
- if (type == SourceType::Raster) {
- result += tileSize == util::tileSize ? "@2x" : "{ratio}";
- }
-
- result += "." + extension;
-
- // get the query and remove access_token, if more parameters exist, add them to the final result
- if (queryIdx != url.length()) {
- const auto query = url.substr(queryIdx + 1);
- std::regex re ("&?access_token=([^&]*)");
- std::string replace = std::regex_replace(query, re, "");
- std::string subQuery = (replace.find("&") == 0) ? replace.substr(1, replace.length()) : replace;
- if (subQuery.length() > 0) result += "?" + subQuery;
+ // Replace PNG with WebP if necessary.
+ if (forceWebP) {
+ result += ".webp";
+ } else {
+ result.append(str, path.extension.first, path.extension.second);
+ }
+
+ // Append the query string, minus the access token parameter.
+ if (url.query.second > 1) {
+ auto idx = url.query.first;
+ bool hasQuery = false;
+ while (idx != std::string::npos) {
+ idx++; // skip & or ?
+ auto ampersandIdx = str.find('&', idx);
+ const char* accessToken = "access_token=";
+ if (str.compare(idx, strlen(accessToken), accessToken) != 0) {
+ result.append(1, hasQuery ? '&' : '?');
+ result.append(str, idx, ampersandIdx != std::string::npos ? ampersandIdx - idx
+ : std::string::npos);
+ hasQuery = true;
+ }
+ idx = ampersandIdx;
+ }
}
return result;
diff --git a/src/mbgl/util/math.hpp b/src/mbgl/util/math.hpp
index 5d4220d0a2..f969ecaedd 100644
--- a/src/mbgl/util/math.hpp
+++ b/src/mbgl/util/math.hpp
@@ -106,11 +106,5 @@ T smoothstep(T edge0, T edge1, T x) {
return t * t * (T(3) - T(2) * t);
}
-// Computes the log2(x) rounded up to the next integer.
-// (== number of bits required to store x)
-uint32_t ceil_log2(uint64_t x);
-
-double log2(double x);
-
} // namespace util
} // namespace mbgl
diff --git a/src/mbgl/util/offscreen_texture.cpp b/src/mbgl/util/offscreen_texture.cpp
index 40bb70b70e..aad20e59d3 100644
--- a/src/mbgl/util/offscreen_texture.cpp
+++ b/src/mbgl/util/offscreen_texture.cpp
@@ -1,15 +1,14 @@
#include <mbgl/util/offscreen_texture.hpp>
#include <mbgl/gl/context.hpp>
-#include <mbgl/gl/gl.hpp>
#include <cstring>
#include <cassert>
namespace mbgl {
-OffscreenTexture::OffscreenTexture(gl::Context& context_, std::array<uint16_t, 2> size_)
- : context(context_), size(std::move(size_)) {
- assert(size[0] > 0 && size[1] > 0);
+OffscreenTexture::OffscreenTexture(gl::Context& context_, const Size size_)
+ : size(std::move(size_)), context(context_) {
+ assert(size);
}
void OffscreenTexture::bind() {
@@ -20,7 +19,7 @@ void OffscreenTexture::bind() {
context.bindFramebuffer = framebuffer->framebuffer;
}
- context.viewport = { 0, 0, size[0], size[1] };
+ context.viewport = { 0, 0, size };
}
gl::Texture& OffscreenTexture::getTexture() {
@@ -29,19 +28,7 @@ gl::Texture& OffscreenTexture::getTexture() {
}
PremultipliedImage OffscreenTexture::readStillImage() {
- PremultipliedImage image { size[0], size[1] };
- MBGL_CHECK_ERROR(glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
-
- const auto stride = image.stride();
- auto tmp = std::make_unique<uint8_t[]>(stride);
- uint8_t* rgba = image.data.get();
- for (int i = 0, j = size[1] - 1; i < j; i++, j--) {
- std::memcpy(tmp.get(), rgba + i * stride, stride);
- std::memcpy(rgba + i * stride, rgba + j * stride, stride);
- std::memcpy(rgba + j * stride, tmp.get(), stride);
- }
-
- return image;
+ return context.readFramebuffer<PremultipliedImage>(size);
}
diff --git a/src/mbgl/util/offscreen_texture.hpp b/src/mbgl/util/offscreen_texture.hpp
index 8928bc2434..64eb7bc565 100644
--- a/src/mbgl/util/offscreen_texture.hpp
+++ b/src/mbgl/util/offscreen_texture.hpp
@@ -14,7 +14,7 @@ class Context;
class OffscreenTexture : public View {
public:
- OffscreenTexture(gl::Context&, std::array<uint16_t, 2> size = {{ 256, 256 }});
+ OffscreenTexture(gl::Context&, Size size = { 256, 256 });
void bind() override;
@@ -22,9 +22,11 @@ public:
gl::Texture& getTexture();
+public:
+ const Size size;
+
private:
gl::Context& context;
- std::array<uint16_t, 2> size;
optional<gl::Framebuffer> framebuffer;
optional<gl::Texture> texture;
};
diff --git a/src/mbgl/util/premultiply.cpp b/src/mbgl/util/premultiply.cpp
index e0178fda33..219273d7cc 100644
--- a/src/mbgl/util/premultiply.cpp
+++ b/src/mbgl/util/premultiply.cpp
@@ -8,12 +8,11 @@ namespace util {
PremultipliedImage premultiply(UnassociatedImage&& src) {
PremultipliedImage dst;
- dst.width = src.width;
- dst.height = src.height;
+ dst.size = src.size;
dst.data = std::move(src.data);
uint8_t* data = dst.data.get();
- for (size_t i = 0; i < dst.size(); i += 4) {
+ for (size_t i = 0; i < dst.bytes(); i += 4) {
uint8_t& r = data[i + 0];
uint8_t& g = data[i + 1];
uint8_t& b = data[i + 2];
@@ -29,12 +28,11 @@ PremultipliedImage premultiply(UnassociatedImage&& src) {
UnassociatedImage unpremultiply(PremultipliedImage&& src) {
UnassociatedImage dst;
- dst.width = src.width;
- dst.height = src.height;
+ dst.size = src.size;
dst.data = std::move(src.data);
uint8_t* data = dst.data.get();
- for (size_t i = 0; i < dst.size(); i += 4) {
+ for (size_t i = 0; i < dst.bytes(); i += 4) {
uint8_t& r = data[i + 0];
uint8_t& g = data[i + 1];
uint8_t& b = data[i + 2];
diff --git a/src/mbgl/util/stopwatch.cpp b/src/mbgl/util/stopwatch.cpp
index d588b79254..3883d8535f 100644
--- a/src/mbgl/util/stopwatch.cpp
+++ b/src/mbgl/util/stopwatch.cpp
@@ -2,7 +2,7 @@
#include <mbgl/util/stopwatch.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/chrono.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <iostream>
#include <atomic>
diff --git a/src/mbgl/util/stopwatch.hpp b/src/mbgl/util/stopwatch.hpp
index 74cc2c412d..6214dae958 100644
--- a/src/mbgl/util/stopwatch.hpp
+++ b/src/mbgl/util/stopwatch.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <mbgl/platform/event.hpp>
+#include <mbgl/util/event.hpp>
#include <mbgl/util/chrono.hpp>
#include <string>
diff --git a/src/mbgl/util/thread.hpp b/src/mbgl/util/thread.hpp
index 91eef745fa..8cfef8a764 100644
--- a/src/mbgl/util/thread.hpp
+++ b/src/mbgl/util/thread.hpp
@@ -8,7 +8,7 @@
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/thread_context.hpp>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/platform.hpp>
#include <pthread.h>
diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp
index c6bf7d362a..2fb7371aba 100644
--- a/src/mbgl/util/tile_cover.cpp
+++ b/src/mbgl/util/tile_cover.cpp
@@ -157,8 +157,8 @@ std::vector<UnwrappedTileID> tileCover(const LatLngBounds& bounds_, int32_t z) {
}
std::vector<UnwrappedTileID> tileCover(const TransformState& state, int32_t z) {
- const double w = state.getWidth();
- const double h = state.getHeight();
+ const double w = state.getSize().width;
+ const double h = state.getSize().height;
return tileCover(
TileCoordinate::fromScreenCoordinate(state, z, { 0, 0 }).p,
TileCoordinate::fromScreenCoordinate(state, z, { w, 0 }).p,
diff --git a/src/mbgl/util/url.cpp b/src/mbgl/util/url.cpp
index bf6fc70ff5..f070135213 100644
--- a/src/mbgl/util/url.cpp
+++ b/src/mbgl/util/url.cpp
@@ -1,11 +1,30 @@
#include <mbgl/util/url.hpp>
+#include <mbgl/util/token.hpp>
-#include <cctype>
#include <iomanip>
#include <sstream>
#include <string>
#include <cstdlib>
#include <algorithm>
+#include <cstring>
+
+namespace {
+
+// std::alnum etc. suffer from locale-dependence.
+
+inline bool isAlphaCharacter(char c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+}
+
+inline bool isAlphaNumericCharacter(char c) {
+ return isAlphaCharacter(c) || (c >= '0' && c <= '9');
+}
+
+inline bool isSchemeCharacter(char c) {
+ return isAlphaNumericCharacter(c) || c == '-' || c == '+' || c == '.';
+}
+
+} // namespace
namespace mbgl {
namespace util {
@@ -17,7 +36,7 @@ std::string percentEncode(const std::string& input) {
encoded << std::hex;
for (auto c : input) {
- if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
+ if (isAlphaNumericCharacter(c) || c == '-' || c == '_' || c == '.' || c == '~') {
encoded << c;
} else {
encoded << '%' << std::setw(2) << int(c);
@@ -47,5 +66,117 @@ std::string percentDecode(const std::string& input) {
return decoded;
}
+// Checks whether the input string contains ://, and the part before it is all alphanumeric ASCII.
+bool isURL(const std::string& input) {
+ auto it = input.begin();
+ // First character has to be alphabetic
+ if (it == input.end() || !isAlphaCharacter(*it++)) return false;
+ // The remaining characters of the scheme can be alphanumeric, or be one of +.-
+ while (it != input.end() && isSchemeCharacter(*it)) ++it;
+ // Check that :// follows
+ return (it != input.end() && *it++ == ':') &&
+ (it != input.end() && *it++ == '/') &&
+ (it != input.end() && *it++ == '/');
+}
+
+URL::URL(const std::string& str)
+ : query([&]() -> Segment {
+ const auto hashPos = str.find('#');
+ const auto queryPos = str.find('?');
+ if (queryPos == std::string::npos || hashPos < queryPos) {
+ return { hashPos != std::string::npos ? hashPos : str.size(), 0 };
+ }
+ return { queryPos, (hashPos != std::string::npos ? hashPos : str.size()) - queryPos };
+ }()),
+ scheme([&]() -> Segment {
+ auto schemeEnd = str.find(':');
+ return { 0, schemeEnd == std::string::npos || schemeEnd > query.first ? 0 : schemeEnd };
+ }()),
+ domain([&]() -> Segment {
+ auto domainPos = scheme.first + scheme.second;
+ while (domainPos < query.first && (str[domainPos] == ':' || str[domainPos] == '/')) {
+ ++domainPos;
+ }
+ const bool isData = str.compare(scheme.first, scheme.second, "data") == 0;
+ const auto endPos = str.find(isData ? ',' : '/', domainPos);
+ return { domainPos, std::min(query.first, endPos) - domainPos };
+ }()),
+ path([&]() -> Segment {
+ auto pathPos = domain.first + domain.second;
+ const bool isData = str.compare(scheme.first, scheme.second, "data") == 0;
+ if (isData) {
+ // Skip comma
+ pathPos++;
+ } else {
+ // Skip optional leading slash
+ while (pathPos < query.first && (str[pathPos] == '/')) {
+ ++pathPos;
+ }
+ }
+ return { pathPos, query.first - pathPos };
+ }()) {
+}
+
+Path::Path(const std::string& str, const size_t pos, const size_t count)
+ : directory([&]() -> Segment {
+ // Finds the string between pos and the first /, if it exists
+ const auto endPos = count == std::string::npos ? str.size() : pos + count;
+ const auto slashPos = str.rfind('/', endPos);
+ return { pos, slashPos == std::string::npos || slashPos < pos ? 0 : slashPos + 1 - pos };
+ }()),
+ extension([&]() -> Segment {
+ auto dotPos = str.rfind('.', pos + count);
+ const auto endPos = count == std::string::npos ? str.size() : pos + count;
+ // Count a preceding @2x to the file extension as well.
+ const char* factor = "@2x";
+ const size_t factorLen = strlen(factor);
+ if (dotPos >= factorLen && dotPos < endPos &&
+ str.compare(dotPos - factorLen, factorLen, factor) == 0) {
+ dotPos -= factorLen;
+ }
+ if (dotPos == std::string::npos || dotPos < directory.first + directory.second) {
+ return { endPos, 0 };
+ }
+ return { dotPos, endPos - dotPos };
+ }()),
+ filename([&]() -> Segment {
+ const auto filePos = directory.first + directory.second;
+ return { filePos, extension.first - filePos };
+ }()) {
+}
+
+std::string transformURL(const std::string& tpl, const std::string& str, const URL& url) {
+ auto result = util::replaceTokens(tpl, [&](const std::string& token) -> std::string {
+ if (token == "path") {
+ return str.substr(url.path.first, url.path.second);
+ } else if (token == "domain") {
+ return str.substr(url.domain.first, url.domain.second);
+ } else if (token == "scheme") {
+ return str.substr(url.scheme.first, url.scheme.second);
+ } else if (token == "directory") {
+ const Path path(str, url.path.first, url.path.second);
+ return str.substr(path.directory.first, path.directory.second);
+ } else if (token == "filename") {
+ const Path path(str, url.path.first, url.path.second);
+ return str.substr(path.filename.first, path.filename.second);
+ } else if (token == "extension") {
+ const Path path(str, url.path.first, url.path.second);
+ return str.substr(path.extension.first, path.extension.second);
+ }
+ return "";
+ });
+
+ // Append the query string if it exists.
+ if (url.query.second > 1) {
+ const auto amp = result.find('?') != std::string::npos ? result.size() : std::string::npos;
+ result.append(str, url.query.first, url.query.second);
+ // Transform the question mark to an ampersand if we had a query string previously.
+ if (amp < result.size()) {
+ result[amp] = '&';
+ }
+ }
+ return result;
+}
+
} // namespace util
} // namespace mbgl
diff --git a/src/mbgl/util/url.hpp b/src/mbgl/util/url.hpp
index b9c66261df..e361b07a7c 100644
--- a/src/mbgl/util/url.hpp
+++ b/src/mbgl/util/url.hpp
@@ -8,6 +8,48 @@ namespace util {
std::string percentEncode(const std::string&);
std::string percentDecode(const std::string&);
+bool isURL(const std::string&);
+
+// Class that holds position + lenth pairs for scheme, domain, path + query string of a URL.
+class URL {
+public:
+ using Segment = std::pair<size_t, size_t>; // position, length
+
+ const Segment query;
+ const Segment scheme;
+ const Segment domain;
+ const Segment path;
+
+ URL(const std::string&);
+};
+
+// Class that holds position + lenth pairs for directory, extension, and filename of a path.
+// The extension will contain the preceding ., and optionally a preceding @2x specifier.
+// The filename will not contain the file extension.
+class Path {
+public:
+ using Segment = std::pair<size_t, size_t>; // position, length
+
+ const Segment directory;
+ const Segment extension;
+ const Segment filename;
+
+ Path(const std::string&, size_t pos = 0, size_t count = std::string::npos);
+};
+
+// Parses the given URL and replaces the tokens in template with parts of the URL.
+// When parsing "http://example.com/foo/bar/baz.png", valid tokens are:
+// * {scheme} == "http"
+// * {domain} == "example.com"
+// * {path} == "foo/bar/baz.png"
+// * {directory} == "foo/bar/"
+// * {filename} == "baz"
+// * {extension} == ".png"
+// The query string of the source URL will always be appended.
+std::string transformURL(const std::string& tpl, const std::string& url, const URL&);
+inline std::string transformURL(const std::string& tpl, const std::string& url) {
+ return transformURL(tpl, url, URL(url));
+}
} // namespace util
} // namespace mbgl
diff --git a/src/mbgl/util/utf.hpp b/src/mbgl/util/utf.hpp
index 560ca3ba7f..81330cfc83 100644
--- a/src/mbgl/util/utf.hpp
+++ b/src/mbgl/util/utf.hpp
@@ -2,18 +2,17 @@
#include <memory>
-#include <boost/regex/pending/unicode_iterator.hpp>
+#include <locale>
+#include <codecvt>
namespace mbgl {
namespace util {
-class utf8_to_utf32 {
- public:
- static std::u32string convert(std::string const& utf8)
- {
- boost::u8_to_u32_iterator<std::string::const_iterator> begin(utf8.begin());
- boost::u8_to_u32_iterator<std::string::const_iterator> end(utf8.end());
- return std::u32string(begin,end);
+class utf8_to_utf16 {
+public:
+ static std::u16string convert(std::string const& utf8) {
+ std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
+ return converter.from_bytes(utf8);
}
};
diff --git a/test/actor/actor.test.cpp b/test/actor/actor.test.cpp
index c24d0b6c25..03f41a6e64 100644
--- a/test/actor/actor.test.cpp
+++ b/test/actor/actor.test.cpp
@@ -1,5 +1,5 @@
#include <mbgl/actor/actor.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/test/util.hpp>
diff --git a/test/actor/actor_ref.test.cpp b/test/actor/actor_ref.test.cpp
index 4be714278e..78721c965e 100644
--- a/test/actor/actor_ref.test.cpp
+++ b/test/actor/actor_ref.test.cpp
@@ -1,5 +1,5 @@
#include <mbgl/actor/actor.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/test/util.hpp>
diff --git a/test/algorithm/generate_clip_ids.test.cpp b/test/algorithm/generate_clip_ids.test.cpp
index 5b7f4afb26..8ca0191b3a 100644
--- a/test/algorithm/generate_clip_ids.test.cpp
+++ b/test/algorithm/generate_clip_ids.test.cpp
@@ -6,6 +6,7 @@ using namespace mbgl;
struct Renderable {
ClipID clip;
+ bool used = true;
bool operator==(const Renderable& rhs) const {
return clip == rhs.clip;
diff --git a/test/api/annotations.test.cpp b/test/api/annotations.test.cpp
index 2c875796bd..72a2d62bde 100644
--- a/test/api/annotations.test.cpp
+++ b/test/api/annotations.test.cpp
@@ -1,12 +1,12 @@
#include <mbgl/test/util.hpp>
#include <mbgl/test/stub_file_source.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/color.hpp>
@@ -23,11 +23,11 @@ std::shared_ptr<SpriteImage> namedMarker(const std::string &name) {
class AnnotationTest {
public:
util::RunLoop loop;
- HeadlessBackend backend;
- OffscreenView view{ backend.getContext() };
+ HeadlessBackend backend { test::sharedDisplay() };
+ OffscreenView view { backend.getContext() };
StubFileSource fileSource;
ThreadPool threadPool { 4 };
- Map map { backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still };
+ Map map { backend, view.size, 1, fileSource, threadPool, MapMode::Still };
void checkRendering(const char * name) {
test::checkImage(std::string("test/fixtures/annotations/") + name,
@@ -45,16 +45,13 @@ TEST(Annotations, SymbolAnnotation) {
test.map.addAnnotation(SymbolAnnotation { Point<double>(0, 0), "default_marker" });
test.checkRendering("point_annotation");
- auto size = test.view.getSize();
- auto screenBox = ScreenBox { {}, { double(size[0]), double(size[1]) } };
- auto features = test.map.queryPointAnnotations(screenBox);
- EXPECT_EQ(features.size(), 1u);
-
- test.map.setZoom(test.map.getMaxZoom());
- test.checkRendering("point_annotation");
-
- features = test.map.queryPointAnnotations(screenBox);
- EXPECT_EQ(features.size(), 1u);
+ auto size = test.view.size;
+ auto screenBox = ScreenBox { {}, { double(size.width), double(size.height) } };
+ for (uint8_t zoom = test.map.getMinZoom(); zoom <= test.map.getMaxZoom(); ++zoom) {
+ test.map.setZoom(zoom);
+ test.checkRendering("point_annotation");
+ EXPECT_EQ(test.map.queryPointAnnotations(screenBox).size(), 1u);
+ }
}
TEST(Annotations, LineAnnotation) {
@@ -62,7 +59,7 @@ TEST(Annotations, LineAnnotation) {
LineString<double> line = {{ { 0, 0 }, { 45, 45 }, { 30, 0 } }};
LineAnnotation annotation { line };
- annotation.color = { { 255, 0, 0, 1 } };
+ annotation.color = Color::red();
annotation.width = { 5 };
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
@@ -78,7 +75,7 @@ TEST(Annotations, FillAnnotation) {
Polygon<double> polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }};
FillAnnotation annotation { polygon };
- annotation.color = { { 255, 0, 0, 1 } };
+ annotation.color = Color::red();
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
test.map.addAnnotation(annotation);
@@ -97,13 +94,13 @@ TEST(Annotations, AntimeridianAnnotationSmall) {
LineString<double> line = {{ { antimeridian, 20 }, { antimeridian, -20 } }};
LineAnnotation lineAnnotation { line };
- lineAnnotation.color = { { 255, 0, 0, 1 } };
+ lineAnnotation.color = Color::red();
lineAnnotation.width = { 2 };
test.map.addAnnotation(lineAnnotation);
Polygon<double> polygon = {{ {{ { antimeridian+10, 0 }, { antimeridian - 10, 10 }, { antimeridian-10, -10 } }} }};
FillAnnotation polygonAnnotation { polygon };
- polygonAnnotation.color = { { 0, 0, 255, 1 } };
+ polygonAnnotation.color = Color::blue();
test.map.addAnnotation(polygonAnnotation);
test.checkRendering("antimeridian_annotation_small");
@@ -118,13 +115,13 @@ TEST(Annotations, AntimeridianAnnotationLarge) {
LineString<double> line = {{ { antimeridian, 20 }, { antimeridian, -20 } }};
LineAnnotation lineAnnotation { line };
- lineAnnotation.color = { { 255, 0, 0, 1 } };
+ lineAnnotation.color = Color::red();
lineAnnotation.width = { 2 };
test.map.addAnnotation(lineAnnotation);
Polygon<double> polygon = {{ {{ { antimeridian-10, 0 }, { -antimeridian+10, 10 }, { -antimeridian+10, -10 } }} }};
FillAnnotation polygonAnnotation { polygon };
- polygonAnnotation.color = { { 0, 0, 255, 1 } };
+ polygonAnnotation.color = Color::blue();
test.map.addAnnotation(polygonAnnotation);
test.checkRendering("antimeridian_annotation_large");
@@ -135,9 +132,9 @@ TEST(Annotations, OverlappingFillAnnotation) {
Polygon<double> polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }};
FillAnnotation underlaidAnnotation { polygon };
- underlaidAnnotation.color = { { 0, 255, 0, 1 } };
+ underlaidAnnotation.color = Color::green();
FillAnnotation overlaidAnnotation { polygon };
- overlaidAnnotation.color = { { 255, 0, 0, 1 } };
+ overlaidAnnotation.color = Color::red();
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
test.map.addAnnotation(underlaidAnnotation);
@@ -176,7 +173,7 @@ TEST(Annotations, NonImmediateAdd) {
Polygon<double> polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }};
FillAnnotation annotation { polygon };
- annotation.color = { { 255, 0, 0, 1 } };
+ annotation.color = Color::red();
test.map.addAnnotation(annotation);
test.checkRendering("non_immediate_add");
@@ -214,7 +211,7 @@ TEST(Annotations, UpdateLineAnnotationGeometry) {
AnnotationTest test;
LineAnnotation annotation { LineString<double> {{ { 0, 0 }, { 45, 45 }, { 30, 0 } }} };
- annotation.color = { { 255, 0, 0, 1 } };
+ annotation.color = Color::red();
annotation.width = { 5 };
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
@@ -231,7 +228,7 @@ TEST(Annotations, UpdateLineAnnotationStyle) {
AnnotationTest test;
LineAnnotation annotation { LineString<double> {{ { 0, 0 }, { 45, 45 }, { 30, 0 } }} };
- annotation.color = { { 255, 0, 0, 1 } };
+ annotation.color = Color::red();
annotation.width = { 5 };
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
@@ -239,7 +236,7 @@ TEST(Annotations, UpdateLineAnnotationStyle) {
test::render(test.map, test.view);
- annotation.color = { { 0, 255, 0, 1 } };
+ annotation.color = Color::green();
annotation.width = { 2 };
test.map.updateAnnotation(line, annotation);
test.checkRendering("update_line_style");
@@ -249,7 +246,7 @@ TEST(Annotations, UpdateFillAnnotationGeometry) {
AnnotationTest test;
FillAnnotation annotation { Polygon<double> {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }} };
- annotation.color = { { 255, 0, 0, 1 } };
+ annotation.color = Color::red();
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
AnnotationID fill = test.map.addAnnotation(annotation);
@@ -266,14 +263,14 @@ TEST(Annotations, UpdateFillAnnotationStyle) {
Polygon<double> polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }};
FillAnnotation annotation { polygon };
- annotation.color = { { 255, 0, 0, 1 } };
+ annotation.color = Color::red();
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
AnnotationID fill = test.map.addAnnotation(annotation);
test::render(test.map, test.view);
- annotation.color = { { 0, 255, 0, 1 } };
+ annotation.color = Color::green();
test.map.updateAnnotation(fill, annotation);
test.checkRendering("update_fill_style");
}
@@ -296,7 +293,7 @@ TEST(Annotations, RemoveShape) {
LineString<double> line = {{ { 0, 0 }, { 45, 45 } }};
LineAnnotation annotation { line };
- annotation.color = { { 255, 0, 0, 1 } };
+ annotation.color = Color::red();
annotation.width = { 5 };
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
@@ -343,19 +340,19 @@ TEST(Annotations, QueryRenderedFeatures) {
auto features = test.map.queryRenderedFeatures(test.map.pixelForLatLng({ 0, 0 }));
EXPECT_EQ(features.size(), 1u);
EXPECT_TRUE(!!features[0].id);
- EXPECT_EQ(*features[0].id, 0);
+ EXPECT_EQ(*features[0].id, uint64_t(0));
auto features2 = test.map.queryRenderedFeatures(test.map.pixelForLatLng({ 50, 0 }));
EXPECT_EQ(features2.size(), 1u);
EXPECT_TRUE(!!features2[0].id);
- EXPECT_EQ(*features2[0].id, 1);
+ EXPECT_EQ(*features2[0].id, uint64_t(1));
}
TEST(Annotations, QueryFractionalZoomLevels) {
AnnotationTest test;
- auto viewSize = test.view.getSize();
- auto box = ScreenBox { {}, { double(viewSize[0]), double(viewSize[1]) } };
+ auto viewSize = test.view.size;
+ auto box = ScreenBox { {}, { double(viewSize.width), double(viewSize.height) } };
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
test.map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
@@ -386,8 +383,8 @@ TEST(Annotations, QueryFractionalZoomLevels) {
TEST(Annotations, VisibleFeatures) {
AnnotationTest test;
- auto viewSize = test.view.getSize();
- auto box = ScreenBox { {}, { double(viewSize[0]), double(viewSize[1]) } };
+ auto viewSize = test.view.size;
+ auto box = ScreenBox { {}, { double(viewSize.width), double(viewSize.height) } };
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
test.map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
@@ -419,3 +416,32 @@ TEST(Annotations, VisibleFeatures) {
features.erase(std::unique(features.begin(), features.end(), sameID), features.end());
EXPECT_EQ(features.size(), ids.size());
}
+
+
+TEST(Annotations, DebugEmpty) {
+ // This test should render nothing, not even the tile borders. Tile borders are only rendered
+ // when there is an actual tile we're trying to render, but since there is no annotation, we
+ // should not render them.
+ AnnotationTest test;
+
+ test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.setDebug(MapDebugOptions::TileBorders);
+ test.map.setZoom(1);
+
+ test.checkRendering("debug_empty");
+}
+
+
+TEST(Annotations, DebugSparse) {
+ // This test should only render the top right tile with the associated tile border, but no other
+ // tiles because they're all empty.
+ AnnotationTest test;
+
+ test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.setDebug(MapDebugOptions::TileBorders);
+ test.map.setZoom(1);
+ test.map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
+ test.map.addAnnotation(SymbolAnnotation { Point<double>(10, 10), "default_marker" });
+
+ test.checkRendering("debug_sparse");
+}
diff --git a/test/api/api_misuse.test.cpp b/test/api/api_misuse.test.cpp
index eb271b0258..34272f5366 100644
--- a/test/api/api_misuse.test.cpp
+++ b/test/api/api_misuse.test.cpp
@@ -3,10 +3,10 @@
#include <mbgl/test/fixture_log_observer.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
#include <mbgl/storage/online_file_source.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/util/run_loop.hpp>
@@ -14,19 +14,20 @@
using namespace mbgl;
+
TEST(API, RenderWithoutCallback) {
auto log = new FixtureLogObserver();
Log::setObserver(std::unique_ptr<Log::Observer>(log));
util::RunLoop loop;
- HeadlessBackend backend;
- OffscreenView view(backend.getContext(), {{ 128, 512 }});
+ HeadlessBackend backend { test::sharedDisplay() };
+ OffscreenView view { backend.getContext(), { 128, 512 } };
StubFileSource fileSource;
ThreadPool threadPool(4);
std::unique_ptr<Map> map =
- std::make_unique<Map>(backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still);
+ std::make_unique<Map>(backend, view.size, 1, fileSource, threadPool, MapMode::Still);
map->renderStill(view, nullptr);
// Force Map thread to join.
@@ -45,12 +46,12 @@ TEST(API, RenderWithoutCallback) {
TEST(API, RenderWithoutStyle) {
util::RunLoop loop;
- HeadlessBackend backend;
- OffscreenView view(backend.getContext(), {{ 128, 512 }});
+ HeadlessBackend backend { test::sharedDisplay() };
+ OffscreenView view { backend.getContext(), { 128, 512 } };
StubFileSource fileSource;
ThreadPool threadPool(4);
- Map map(backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still);
+ Map map(backend, view.size, 1, fileSource, threadPool, MapMode::Still);
std::exception_ptr error;
map.renderStill(view, [&](std::exception_ptr error_) {
diff --git a/test/api/custom_layer.test.cpp b/test/api/custom_layer.test.cpp
index 70de102b80..73b4e94af5 100644
--- a/test/api/custom_layer.test.cpp
+++ b/test/api/custom_layer.test.cpp
@@ -2,9 +2,9 @@
#include <mbgl/gl/gl.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
@@ -85,8 +85,8 @@ public:
TEST(CustomLayer, Basic) {
util::RunLoop loop;
- HeadlessBackend backend;
- OffscreenView view(backend.getContext());
+ HeadlessBackend backend { test::sharedDisplay() };
+ OffscreenView view { backend.getContext() };
#ifdef MBGL_ASSET_ZIP
// Regenerate with `cd test/fixtures/api/ && zip -r assets.zip assets/`
@@ -97,7 +97,7 @@ TEST(CustomLayer, Basic) {
ThreadPool threadPool(4);
- Map map(backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still);
+ Map map(backend, view.size, 1, fileSource, threadPool, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/water.json"));
map.setLatLngZoom({ 37.8, -122.5 }, 10);
map.addLayer(std::make_unique<CustomLayer>(
diff --git a/test/api/query.test.cpp b/test/api/query.test.cpp
index 8e59c19afc..86687fc818 100644
--- a/test/api/query.test.cpp
+++ b/test/api/query.test.cpp
@@ -1,7 +1,7 @@
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/test/stub_file_source.hpp>
#include <mbgl/test/util.hpp>
@@ -26,11 +26,11 @@ public:
}
util::RunLoop loop;
- HeadlessBackend backend;
+ HeadlessBackend backend { test::sharedDisplay() };
OffscreenView view { backend.getContext() };
StubFileSource fileSource;
ThreadPool threadPool { 4 };
- Map map { backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still };
+ Map map { backend, view.size, 1, fileSource, threadPool, MapMode::Still };
};
} // end namespace
diff --git a/test/api/render_missing.test.cpp b/test/api/render_missing.test.cpp
index 366d71e67d..a5c59913bc 100644
--- a/test/api/render_missing.test.cpp
+++ b/test/api/render_missing.test.cpp
@@ -2,9 +2,9 @@
#include <mbgl/test/fixture_log_observer.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
@@ -25,8 +25,8 @@ TEST(API, TEST_REQUIRES_SERVER(RenderMissingTile)) {
const auto style = util::read_file("test/fixtures/api/water_missing_tiles.json");
- HeadlessBackend backend;
- OffscreenView view(backend.getContext(), {{ 256, 512 }});
+ HeadlessBackend backend { test::sharedDisplay() };
+ OffscreenView view { backend.getContext(), { 256, 512 } };
#ifdef MBGL_ASSET_ZIP
// Regenerate with `cd test/fixtures/api/ && zip -r assets.zip assets/`
DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets.zip");
@@ -38,7 +38,7 @@ TEST(API, TEST_REQUIRES_SERVER(RenderMissingTile)) {
Log::setObserver(std::make_unique<FixtureLogObserver>());
- Map map(backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still);
+ Map map(backend, view.size, 1, fileSource, threadPool, MapMode::Still);
std::string message;
diff --git a/test/api/repeated_render.test.cpp b/test/api/repeated_render.test.cpp
index 715b49b289..49b9a31b0b 100644
--- a/test/api/repeated_render.test.cpp
+++ b/test/api/repeated_render.test.cpp
@@ -2,9 +2,9 @@
#include <mbgl/test/fixture_log_observer.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
@@ -12,15 +12,17 @@
#include <future>
+using namespace mbgl;
+
+
TEST(API, RepeatedRender) {
- using namespace mbgl;
util::RunLoop loop;
const auto style = util::read_file("test/fixtures/api/water.json");
- HeadlessBackend backend;
- OffscreenView view(backend.getContext(), {{ 256, 512 }});
+ HeadlessBackend backend { test::sharedDisplay() };
+ OffscreenView view { backend.getContext(), { 256, 512 } };
#ifdef MBGL_ASSET_ZIP
// Regenerate with `cd test/fixtures/api/ && zip -r assets.zip assets/`
DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets.zip");
@@ -32,7 +34,7 @@ TEST(API, RepeatedRender) {
Log::setObserver(std::make_unique<FixtureLogObserver>());
- Map map(backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still);
+ Map map(backend, view.size, 1, fileSource, threadPool, MapMode::Still);
{
map.setStyleJSON(style);
@@ -41,12 +43,12 @@ TEST(API, RepeatedRender) {
result = view.readStillImage();
});
- while (!result.size()) {
+ while (!result.valid()) {
loop.runOnce();
}
- ASSERT_EQ(256u, result.width);
- ASSERT_EQ(512u, result.height);
+ ASSERT_EQ(256u, result.size.width);
+ ASSERT_EQ(512u, result.size.height);
#if !TEST_READ_ONLY
util::write_file("test/fixtures/api/1.png", encodePNG(result));
#endif
@@ -59,12 +61,12 @@ TEST(API, RepeatedRender) {
result = view.readStillImage();
});
- while (!result.size()) {
+ while (!result.valid()) {
loop.runOnce();
}
- ASSERT_EQ(256u, result.width);
- ASSERT_EQ(512u, result.height);
+ ASSERT_EQ(256u, result.size.width);
+ ASSERT_EQ(512u, result.size.height);
#if !TEST_READ_ONLY
util::write_file("test/fixtures/api/2.png", encodePNG(result));
#endif
diff --git a/test/fixtures/annotations/assets.zip b/test/fixtures/annotations/assets.zip
deleted file mode 100644
index 869380034f..0000000000
--- a/test/fixtures/annotations/assets.zip
+++ /dev/null
Binary files differ
diff --git a/test/fixtures/annotations/debug_empty/expected.png b/test/fixtures/annotations/debug_empty/expected.png
new file mode 100644
index 0000000000..04f8682f88
--- /dev/null
+++ b/test/fixtures/annotations/debug_empty/expected.png
Binary files differ
diff --git a/test/fixtures/annotations/debug_sparse/expected.png b/test/fixtures/annotations/debug_sparse/expected.png
new file mode 100644
index 0000000000..3c1ad1599c
--- /dev/null
+++ b/test/fixtures/annotations/debug_sparse/expected.png
Binary files differ
diff --git a/test/fixtures/api/assets.zip b/test/fixtures/api/assets.zip
deleted file mode 100644
index fe00443f61..0000000000
--- a/test/fixtures/api/assets.zip
+++ /dev/null
Binary files differ
diff --git a/test/fixtures/storage/assets.zip b/test/fixtures/storage/assets.zip
deleted file mode 100644
index 4006ee10f2..0000000000
--- a/test/fixtures/storage/assets.zip
+++ /dev/null
Binary files differ
diff --git a/test/fixtures/style_parser/stop-zoom-value.info.json b/test/fixtures/style_parser/stop-zoom-value.info.json
index 386dce9d29..39d7c68495 100644
--- a/test/fixtures/style_parser/stop-zoom-value.info.json
+++ b/test/fixtures/style_parser/stop-zoom-value.info.json
@@ -1,6 +1,7 @@
{
"default": {
"log": [
+ [1, "WARNING", "ParseStyle", "function must have at least one stop"],
[1, "WARNING", "ParseStyle", "function stop must have two elements"]
]
}
diff --git a/test/gl/bucket.test.cpp b/test/gl/bucket.test.cpp
new file mode 100644
index 0000000000..03cdc63a91
--- /dev/null
+++ b/test/gl/bucket.test.cpp
@@ -0,0 +1,41 @@
+#include <mbgl/test/util.hpp>
+
+#include <mbgl/renderer/circle_bucket.hpp>
+#include <mbgl/renderer/fill_bucket.hpp>
+#include <mbgl/renderer/line_bucket.hpp>
+#include <mbgl/renderer/symbol_bucket.hpp>
+
+#include <mbgl/style/layers/symbol_layer_properties.hpp>
+
+#include <mbgl/map/mode.hpp>
+
+TEST(Buckets, CircleBucket) {
+ mbgl::MapMode mapMode = mbgl::MapMode::Still;
+
+ mbgl::CircleBucket bucket { mapMode };
+ ASSERT_FALSE(bucket.hasData());
+}
+
+TEST(Buckets, FillBucket) {
+ mbgl::FillBucket bucket;
+ ASSERT_FALSE(bucket.hasData());
+}
+
+TEST(Buckets, LineBucket) {
+ uint32_t overscaling = 0;
+
+ mbgl::LineBucket bucket { overscaling };
+ ASSERT_FALSE(bucket.hasData());
+}
+
+TEST(Buckets, SymbolBucket) {
+ mbgl::MapMode mapMode = mbgl::MapMode::Still;
+ mbgl::style::SymbolLayoutProperties::Evaluated properties;
+ bool sdfIcons = false;
+ bool iconsNeedLinear = false;
+
+ mbgl::SymbolBucket bucket { mapMode, properties, sdfIcons, iconsNeedLinear };
+ ASSERT_FALSE(bucket.hasIconData());
+ ASSERT_FALSE(bucket.hasTextData());
+ ASSERT_FALSE(bucket.hasCollisionBoxData());
+}
diff --git a/test/gl/object.test.cpp b/test/gl/object.test.cpp
index a3457d28c6..f1da93f1da 100644
--- a/test/gl/object.test.cpp
+++ b/test/gl/object.test.cpp
@@ -1,13 +1,14 @@
#include <mbgl/test/util.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
-#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/context.hpp>
#include <memory>
+using namespace mbgl;
+
namespace {
static bool getFlag = false;
@@ -28,7 +29,7 @@ TEST(GLObject, PreserveState) {
getFlag = false;
setFlag = false;
- auto object = std::make_unique<mbgl::gl::PreserveState<MockGLObject>>();
+ auto object = std::make_unique<gl::PreserveState<MockGLObject>>();
EXPECT_TRUE(getFlag);
EXPECT_FALSE(setFlag);
@@ -41,7 +42,7 @@ TEST(GLObject, PreserveState) {
TEST(GLObject, Value) {
setFlag = false;
- auto object = std::make_unique<mbgl::gl::State<MockGLObject>>();
+ auto object = std::make_unique<gl::State<MockGLObject>>();
EXPECT_EQ(object->getCurrentValue(), false);
EXPECT_TRUE(object->isDirty());
EXPECT_FALSE(setFlag);
@@ -59,27 +60,13 @@ TEST(GLObject, Value) {
}
TEST(GLObject, Store) {
- mbgl::HeadlessBackend backend;
- mbgl::OffscreenView view(backend.getContext());
+ HeadlessBackend backend { test::sharedDisplay() };
+ OffscreenView view(backend.getContext());
- mbgl::gl::Context context;
+ gl::Context context;
EXPECT_TRUE(context.empty());
- mbgl::gl::UniqueProgram program = context.createProgram();
- EXPECT_NE(program.get(), 0u);
- program.reset();
- EXPECT_FALSE(context.empty());
- context.performCleanup();
- EXPECT_TRUE(context.empty());
-
- mbgl::gl::UniqueShader shader = context.createVertexShader();
- EXPECT_NE(shader.get(), 0u);
- shader.reset();
- EXPECT_FALSE(context.empty());
- context.performCleanup();
- EXPECT_TRUE(context.empty());
-
- mbgl::gl::UniqueTexture texture = context.createTexture();
+ gl::UniqueTexture texture = context.createTexture();
EXPECT_NE(texture.get(), 0u);
texture.reset();
EXPECT_FALSE(context.empty());
@@ -88,13 +75,6 @@ TEST(GLObject, Store) {
context.reset();
EXPECT_TRUE(context.empty());
- mbgl::gl::UniqueVertexArray vao = context.createVertexArray();
- EXPECT_NE(vao.get(), 0u);
- vao.reset();
- EXPECT_FALSE(context.empty());
- context.performCleanup();
- EXPECT_TRUE(context.empty());
-
context.reset();
EXPECT_TRUE(context.empty());
diff --git a/test/map/map.test.cpp b/test/map/map.test.cpp
index 5311aeb17f..8eedeb3c01 100644
--- a/test/map/map.test.cpp
+++ b/test/map/map.test.cpp
@@ -4,15 +4,16 @@
#include <mbgl/test/fixture_log_observer.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
+#include <mbgl/util/async_task.hpp>
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/util/color.hpp>
@@ -22,7 +23,7 @@ using namespace std::literals::string_literals;
struct MapTest {
util::RunLoop runLoop;
- HeadlessBackend backend;
+ HeadlessBackend backend { test::sharedDisplay() };
OffscreenView view { backend.getContext() };
StubFileSource fileSource;
ThreadPool threadPool { 4 };
@@ -30,7 +31,7 @@ struct MapTest {
TEST(Map, LatLngBehavior) {
MapTest test;
- Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
@@ -64,7 +65,7 @@ TEST(Map, Offline) {
fileSource.put(Resource::glyphs(prefix + "{fontstack}/{range}.pbf", {{"Helvetica"}}, {0, 255}), expiredItem("glyph.pbf"));
NetworkStatus::Set(NetworkStatus::Status::Offline);
- Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, fileSource, test.threadPool, MapMode::Still);
map.setStyleURL(prefix + "style.json");
test::checkImage("test/fixtures/map/offline",
@@ -88,7 +89,7 @@ TEST(Map, SetStyleInvalidJSON) {
});
{
- Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool,
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool,
MapMode::Still);
map.setStyleJSON("invalid");
}
@@ -120,7 +121,7 @@ TEST(Map, SetStyleInvalidURL) {
}
});
- Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleURL("mapbox://bar");
test.runLoop.run();
@@ -129,7 +130,7 @@ TEST(Map, SetStyleInvalidURL) {
TEST(Map, DoubleStyleLoad) {
MapTest test;
- Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleJSON("");
map.setStyleJSON("");
}
@@ -140,7 +141,7 @@ TEST(Map, StyleFresh) {
MapTest test;
FakeFileSource fileSource;
- Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, fileSource, test.threadPool, MapMode::Still);
map.setStyleURL("mapbox://styles/test");
EXPECT_EQ(1u, fileSource.requests.size());
@@ -160,7 +161,7 @@ TEST(Map, StyleExpired) {
MapTest test;
FakeFileSource fileSource;
- Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, fileSource, test.threadPool, MapMode::Still);
map.setStyleURL("mapbox://styles/test");
EXPECT_EQ(1u, fileSource.requests.size());
@@ -187,7 +188,7 @@ TEST(Map, StyleExpiredWithAnnotations) {
MapTest test;
FakeFileSource fileSource;
- Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, fileSource, test.threadPool, MapMode::Still);
map.setStyleURL("mapbox://styles/test");
EXPECT_EQ(1u, fileSource.requests.size());
@@ -211,7 +212,7 @@ TEST(Map, StyleEarlyMutation) {
MapTest test;
FakeFileSource fileSource;
- Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, fileSource, test.threadPool, MapMode::Still);
map.setStyleURL("mapbox://styles/test");
map.addLayer(std::make_unique<style::BackgroundLayer>("bg"));
@@ -225,7 +226,7 @@ TEST(Map, StyleEarlyMutation) {
TEST(Map, StyleLoadedSignal) {
MapTest test;
- Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
// The map should emit a signal on style loaded
bool emitted = false;
@@ -246,7 +247,7 @@ TEST(Map, StyleLoadedSignal) {
TEST(Map, AddLayer) {
MapTest test;
- Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
auto layer = std::make_unique<BackgroundLayer>("background");
@@ -259,7 +260,7 @@ TEST(Map, AddLayer) {
TEST(Map, RemoveLayer) {
MapTest test;
- Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
auto layer = std::make_unique<BackgroundLayer>("background");
@@ -284,7 +285,7 @@ TEST(Map, DisabledSources) {
return {};
};
- Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
map.setZoom(1);
// This stylesheet has two raster layers, one that starts at zoom 1, the other at zoom 0.
@@ -334,7 +335,7 @@ TEST(Map, DisabledSources) {
TEST(Map, Classes) {
MapTest test;
- Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
EXPECT_FALSE(map.getTransitionOptions().duration);
@@ -368,7 +369,7 @@ TEST(Map, Classes) {
TEST(Map, AddImage) {
MapTest test;
- Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
auto decoded1 = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png"));
auto decoded2 = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png"));
auto image1 = std::make_unique<SpriteImage>(std::move(decoded1), 1.0);
@@ -385,7 +386,7 @@ TEST(Map, AddImage) {
TEST(Map, RemoveImage) {
MapTest test;
- Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
auto decoded = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png"));
auto image = std::make_unique<SpriteImage>(std::move(decoded), 1.0);
@@ -398,7 +399,7 @@ TEST(Map, RemoveImage) {
TEST(Map, GetImage) {
MapTest test;
- Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
auto decoded = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png"));
auto image = std::make_unique<SpriteImage>(std::move(decoded), 1.0);
@@ -406,3 +407,113 @@ TEST(Map, GetImage) {
map.addImage("test-icon", std::move(image));
test::checkImage("test/fixtures/map/get_icon", map.getImage("test-icon")->image);
}
+
+TEST(Map, DontLoadUnneededTiles) {
+ MapTest test;
+
+ Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
+ map.setStyleJSON(R"STYLE({
+ "sources": {
+ "a": { "type": "vector", "tiles": [ "a/{z}/{x}/{y}" ] }
+ },
+ "layers": [{
+ "id": "a",
+ "type": "fill",
+ "source": "a",
+ "source-layer": "a",
+ "minzoom": 0.3,
+ "maxzoom": 1.6
+ }]
+})STYLE");
+
+ using Tiles = std::unordered_set<std::string>;
+ Tiles tiles;
+
+ test.fileSource.tileResponse = [&](const Resource& rsc) {
+ tiles.emplace(rsc.url);
+ Response res;
+ res.noContent = true;
+ return res;
+ };
+
+ std::unordered_map<double, Tiles> referenceTiles = {
+ // Since the layer's minzoom is 0.3, we shouldn't load tiles before z0.3
+ { 0.3, { "a/0/0/0" } },
+ { 1.0, { "a/1/1/0", "a/1/0/1", "a/1/0/0", "a/1/1/1" } },
+ // Since the layer's maxzoom is 1.6, we should never load z2 or z3 tiles.
+ };
+
+ // Loop through zoom levels from 0 to 3 and check that the correct tiles are loaded at every
+ // step. The source is marked with maxzoom 1.0, which means that it won't be visible anymore
+ // after z1.0, so we should under no circumstances attempt to load z2 tiles.
+ for (unsigned zoom = 0; zoom <= 30; zoom++) { // times 10
+ // Note: using z += 0.1 in the loop doesn't produce accurate floating point numbers.
+ const double z = double(zoom) / 10;
+ tiles.clear();
+ map.setZoom(z);
+ test::render(map, test.view);
+ EXPECT_EQ(referenceTiles[z], tiles) << "zoom level " << z;
+ }
+}
+
+
+class MockBackend : public HeadlessBackend {
+public:
+ MockBackend(std::shared_ptr<HeadlessDisplay> display_)
+ : HeadlessBackend(display_) {
+ }
+
+ std::function<void()> callback;
+ void invalidate() override {
+ if (callback) {
+ callback();
+ }
+ }
+};
+
+TEST(Map, TEST_DISABLED_ON_CI(ContinuousRendering)) {
+ util::RunLoop runLoop;
+ MockBackend backend { test::sharedDisplay() };
+ OffscreenView view { backend.getContext() };
+ ThreadPool threadPool { 4 };
+
+#ifdef MBGL_ASSET_ZIP
+ // Regenerate with `cd test/fixtures/api/ && zip -r assets.zip assets/`
+ DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets.zip");
+#else
+ DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets");
+#endif
+
+ Map map(backend, view.size, 1, fileSource, threadPool, MapMode::Continuous);
+
+ using namespace std::chrono_literals;
+
+ util::Timer emergencyShutoff;
+ emergencyShutoff.start(10s, 0s, [&] {
+ util::RunLoop::Get()->stop();
+ FAIL() << "Did not stop rendering";
+ });
+
+ util::Timer timer;
+ util::AsyncTask render{[&] {
+ if (map.isFullyLoaded()) {
+ // Abort the test after 1 second after the map loading fully. Note that a "fully loaded
+ // map" doesn't mean that we won't render anymore: we could still render fade in/fade
+ // out or other animations.
+ // If we are continuing to render indefinitely, the emergency shutoff above will trigger
+ // and the test will fail since the regular time will be constantly reset.
+ timer.start(1s, 0s, [&] {
+ util::RunLoop::Get()->stop();
+ });
+ }
+
+ map.render(view);
+ }};
+
+ backend.callback = [&] {
+ render.send();
+ };
+
+ map.setStyleJSON(util::read_file("test/fixtures/api/water.json"));
+ util::RunLoop::Get()->run();
+}
diff --git a/test/map/transform.test.cpp b/test/map/transform.test.cpp
index afb655abca..d5b98ac109 100644
--- a/test/map/transform.test.cpp
+++ b/test/map/transform.test.cpp
@@ -103,11 +103,40 @@ TEST(Transform, InvalidBearing) {
ASSERT_DOUBLE_EQ(2, transform.getAngle());
}
+TEST(Transform, IntegerZoom) {
+ Transform transform;
+
+ auto checkIntegerZoom = [&transform](uint8_t zoomInt, double zoom) {
+ double scale = transform.getState().zoomScale(zoom);
+ transform.setScale(scale);
+#if __ANDROID__
+ // Android uses log(x) / M_LN2 instead of log2(x) because the latter
+ // is _broken in ARMv5 - that approach being less precise than log2(x).
+ ASSERT_NEAR(transform.getScale(), scale, 0.0001);
+#else
+ ASSERT_DOUBLE_EQ(transform.getScale(), scale);
+#endif
+ ASSERT_NEAR(transform.getZoom(), zoom, 0.0001);
+ ASSERT_EQ(transform.getState().getIntegerZoom(), zoomInt);
+ ASSERT_NEAR(transform.getState().getZoomFraction(), zoom - zoomInt, 0.0001);
+ };
+
+ for (uint8_t zoomInt = 0; zoomInt < 20; ++zoomInt) {
+ for (uint32_t percent = 0; percent < 100; ++percent) {
+ double zoom = zoomInt + (0.01 * percent);
+ checkIntegerZoom(zoomInt, zoom);
+ }
+ }
+
+ // Special case zoom 20.
+ checkIntegerZoom(20, 20.0);
+}
+
TEST(Transform, PerspectiveProjection) {
LatLng loc;
Transform transform;
- transform.resize({{ 1000, 1000 }});
+ transform.resize({ 1000, 1000 });
transform.setScale(2 << 9);
transform.setPitch(0.9);
transform.setLatLng(LatLng(38, -77));
@@ -137,7 +166,7 @@ TEST(Transform, PerspectiveProjection) {
TEST(Transform, UnwrappedLatLng) {
Transform transform;
- transform.resize({{ 1000, 1000 }});
+ transform.resize({ 1000, 1000 });
transform.setScale(2 << 9);
transform.setPitch(0.9);
transform.setLatLng(LatLng(38, -77));
@@ -169,7 +198,7 @@ TEST(Transform, ConstrainHeightOnly) {
LatLng loc;
Transform transform;
- transform.resize({{ 1000, 1000 }});
+ transform.resize({ 1000, 1000 });
transform.setScale(std::pow(2, util::MAX_ZOOM));
transform.setLatLng(LatLngBounds::world().southwest());
@@ -187,7 +216,7 @@ TEST(Transform, ConstrainWidthAndHeight) {
LatLng loc;
Transform transform(nullptr, ConstrainMode::WidthAndHeight);
- transform.resize({{ 1000, 1000 }});
+ transform.resize({ 1000, 1000 });
transform.setScale(std::pow(2, util::MAX_ZOOM));
transform.setLatLng(LatLngBounds::world().southwest());
@@ -203,7 +232,7 @@ TEST(Transform, ConstrainWidthAndHeight) {
TEST(Transform, Anchor) {
Transform transform;
- transform.resize({{ 1000, 1000 }});
+ transform.resize({ 1000, 1000 });
const LatLng latLng { 10, -100 };
transform.setLatLngZoom(latLng, 10);
@@ -303,7 +332,7 @@ TEST(Transform, Anchor) {
TEST(Transform, Padding) {
Transform transform;
- transform.resize({{ 1000, 1000 }});
+ transform.resize({ 1000, 1000 });
ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude);
ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude);
@@ -333,14 +362,14 @@ TEST(Transform, Padding) {
const LatLng shiftedCenter = transform.getLatLng(padding);
ASSERT_NE(trueCenter.latitude, shiftedCenter.latitude);
- ASSERT_DOUBLE_EQ(trueCenter.longitude, shiftedCenter.longitude);
+ ASSERT_NEAR(trueCenter.longitude, shiftedCenter.longitude, 1e-9);
ASSERT_DOUBLE_EQ(manualShiftedCenter.latitude, shiftedCenter.latitude);
ASSERT_DOUBLE_EQ(manualShiftedCenter.longitude, shiftedCenter.longitude);
}
TEST(Transform, MoveBy) {
Transform transform;
- transform.resize({{ 1000, 1000 }});
+ transform.resize({ 1000, 1000 });
transform.setLatLngZoom({ 0, 0 }, 10);
LatLng trueCenter = transform.getLatLng();
@@ -367,17 +396,17 @@ TEST(Transform, MoveBy) {
TEST(Transform, Antimeridian) {
Transform transform;
- transform.resize({{ 1000, 1000 }});
+ transform.resize({ 1000, 1000 });
transform.setLatLngZoom({ 0, 0 }, 1);
const LatLng coordinateSanFrancisco { 37.7833, -122.4167 };
ScreenCoordinate pixelSF = transform.latLngToScreenCoordinate(coordinateSanFrancisco);
- ASSERT_DOUBLE_EQ(151.79409149185352, pixelSF.x);
- ASSERT_DOUBLE_EQ(383.76774094913071, pixelSF.y);
+ ASSERT_NEAR(151.79409149185352, pixelSF.x, 1e-2);
+ ASSERT_NEAR(383.76774094913071, pixelSF.y, 1e-2);
transform.setLatLng({ 0, -181 });
ScreenCoordinate pixelSFBackwards = transform.latLngToScreenCoordinate(coordinateSanFrancisco);
- ASSERT_DOUBLE_EQ(666.63617954008976, pixelSFBackwards.x);
+ ASSERT_NEAR(666.63617954008976, pixelSFBackwards.x, 1e-2);
ASSERT_DOUBLE_EQ(pixelSF.y, pixelSFBackwards.y);
transform.setLatLng({ 0, 179 });
@@ -388,12 +417,12 @@ TEST(Transform, Antimeridian) {
const LatLng coordinateWaikiri{ -16.9310, 179.9787 };
transform.setLatLngZoom(coordinateWaikiri, 10);
ScreenCoordinate pixelWaikiri = transform.latLngToScreenCoordinate(coordinateWaikiri);
- ASSERT_DOUBLE_EQ(500.00000000007759, pixelWaikiri.x);
- ASSERT_DOUBLE_EQ(500, pixelWaikiri.y);
+ ASSERT_NEAR(500, pixelWaikiri.x, 1e-2);
+ ASSERT_NEAR(500, pixelWaikiri.y, 1e-2);
transform.setLatLng({ coordinateWaikiri.latitude, 180.0213 });
ScreenCoordinate pixelWaikiriForwards = transform.latLngToScreenCoordinate(coordinateWaikiri);
- ASSERT_DOUBLE_EQ(437.95953728819512, pixelWaikiriForwards.x);
+ ASSERT_NEAR(437.95953728819512, pixelWaikiriForwards.x, 1e-2);
ASSERT_DOUBLE_EQ(pixelWaikiri.y, pixelWaikiriForwards.y);
LatLng coordinateFromPixel = transform.screenCoordinateToLatLng(pixelWaikiriForwards);
ASSERT_NEAR(coordinateWaikiri.latitude, coordinateFromPixel.latitude, 0.000001);
@@ -410,7 +439,7 @@ TEST(Transform, Antimeridian) {
TEST(Transform, Camera) {
Transform transform;
- transform.resize({{ 1000, 1000 }});
+ transform.resize({ 1000, 1000 });
const LatLng latLng1 { 45, 135 };
CameraOptions cameraOptions1;
@@ -481,8 +510,8 @@ TEST(Transform, DefaultTransform) {
LatLng nullIsland, latLng = {};
ScreenCoordinate center, point = {};
- const uint16_t min = std::numeric_limits<uint16_t>::min();
- const uint16_t max = std::numeric_limits<uint16_t>::max();
+ const uint32_t min = 0;
+ const uint32_t max = 65535;
auto testConversions = [&](const LatLng& coord, const ScreenCoordinate& screenCoord) {
latLng = state.screenCoordinateToLatLng(center);
@@ -496,21 +525,21 @@ TEST(Transform, DefaultTransform) {
testConversions(nullIsland, center);
// Cannot assign the current size.
- ASSERT_FALSE(transform.resize({{}}));
+ ASSERT_FALSE(transform.resize({}));
- ASSERT_TRUE(transform.resize({{ min, max }}));
+ ASSERT_TRUE(transform.resize({ min, max }));
testConversions(nullIsland, center);
- ASSERT_TRUE(transform.resize({{ max, min }}));
+ ASSERT_TRUE(transform.resize({ max, min }));
testConversions(nullIsland, center);
- ASSERT_TRUE(transform.resize({{ min, min }}));
+ ASSERT_TRUE(transform.resize({ min, min }));
testConversions(nullIsland, center);
center = { max / 2., max / 2. };
- // -1 evaluates to UINT_MAX.
- ASSERT_TRUE(transform.resize({{ static_cast<uint16_t>(-1), static_cast<uint16_t>(-1) }}));
- ASSERT_FALSE(transform.resize({{ max, max }}));
+ // Double resize
+ ASSERT_TRUE(transform.resize({ max, max }));
+ ASSERT_FALSE(transform.resize({ max, max }));
testConversions(nullIsland, center);
}
diff --git a/test/sprite/sprite_atlas.test.cpp b/test/sprite/sprite_atlas.test.cpp
index f84e17cbcf..c9576013d4 100644
--- a/test/sprite/sprite_atlas.test.cpp
+++ b/test/sprite/sprite_atlas.test.cpp
@@ -21,14 +21,6 @@ auto readImage(const std::string& name) {
return decodeImage(util::read_file(name));
}
-auto imageFromAtlas(const SpriteAtlas& atlas) {
- const size_t bytes = atlas.getTextureWidth() * atlas.getTextureHeight() * 4;
- auto data = std::make_unique<uint8_t[]>(bytes);
- const auto src = reinterpret_cast<const uint8_t*>(atlas.getData());
- std::copy(src, src + bytes, data.get());
- return PremultipliedImage{ atlas.getTextureWidth(), atlas.getTextureHeight(), std::move(data) };
-}
-
} // namespace
TEST(SpriteAtlas, Basic) {
@@ -37,17 +29,12 @@ TEST(SpriteAtlas, Basic) {
auto spriteParseResult = parseSprite(util::read_file("test/fixtures/annotations/emerald.png"),
util::read_file("test/fixtures/annotations/emerald.json"));
- SpriteAtlas atlas(63, 112, 1);
+ SpriteAtlas atlas({ 63, 112 }, 1);
atlas.setSprites(spriteParseResult.get<Sprites>());
EXPECT_EQ(1.0f, atlas.getPixelRatio());
- EXPECT_EQ(63, atlas.getWidth());
- EXPECT_EQ(112, atlas.getHeight());
- EXPECT_EQ(63, atlas.getTextureWidth());
- EXPECT_EQ(112, atlas.getTextureHeight());
-
- // Image hasn't been created yet.
- EXPECT_FALSE(atlas.getData());
+ EXPECT_EQ(63u, atlas.getSize().width);
+ EXPECT_EQ(112u, atlas.getSize().height);
auto metro = *atlas.getImage("metro", SpritePatternMode::Single);
EXPECT_EQ(0, metro.pos.x);
@@ -56,11 +43,12 @@ TEST(SpriteAtlas, Basic) {
EXPECT_EQ(20, metro.pos.h);
EXPECT_EQ(18, metro.spriteImage->getWidth());
EXPECT_EQ(18, metro.spriteImage->getHeight());
- EXPECT_EQ(18u, metro.spriteImage->image.width);
- EXPECT_EQ(18u, metro.spriteImage->image.height);
+ EXPECT_EQ(18u, metro.spriteImage->image.size.width);
+ EXPECT_EQ(18u, metro.spriteImage->image.size.height);
EXPECT_EQ(1.0f, metro.spriteImage->pixelRatio);
- EXPECT_TRUE(atlas.getData());
+ EXPECT_EQ(63u, atlas.getAtlasImage().size.width);
+ EXPECT_EQ(112u, atlas.getAtlasImage().size.height);
auto pos = *atlas.getPosition("metro", SpritePatternMode::Single);
EXPECT_DOUBLE_EQ(18, pos.size[0]);
@@ -87,21 +75,19 @@ TEST(SpriteAtlas, Basic) {
EXPECT_EQ(20, metro2.pos.w);
EXPECT_EQ(20, metro2.pos.h);
- EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas.png"), imageFromAtlas(atlas));
+ EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas.png"), atlas.getAtlasImage());
}
TEST(SpriteAtlas, Size) {
auto spriteParseResult = parseSprite(util::read_file("test/fixtures/annotations/emerald.png"),
util::read_file("test/fixtures/annotations/emerald.json"));
- SpriteAtlas atlas(63, 112, 1.4);
+ SpriteAtlas atlas({ 63, 112 }, 1.4);
atlas.setSprites(spriteParseResult.get<Sprites>());
EXPECT_DOUBLE_EQ(1.4f, atlas.getPixelRatio());
- EXPECT_EQ(63, atlas.getWidth());
- EXPECT_EQ(112, atlas.getHeight());
- EXPECT_EQ(89, atlas.getTextureWidth());
- EXPECT_EQ(157, atlas.getTextureHeight());
+ EXPECT_EQ(63u, atlas.getSize().width);
+ EXPECT_EQ(112u, atlas.getSize().height);
auto metro = *atlas.getImage("metro", SpritePatternMode::Single);
EXPECT_EQ(0, metro.pos.x);
@@ -110,24 +96,26 @@ TEST(SpriteAtlas, Size) {
EXPECT_EQ(16, metro.pos.h);
EXPECT_EQ(18, metro.spriteImage->getWidth());
EXPECT_EQ(18, metro.spriteImage->getHeight());
- EXPECT_EQ(18u, metro.spriteImage->image.width);
- EXPECT_EQ(18u, metro.spriteImage->image.height);
+ EXPECT_EQ(18u, metro.spriteImage->image.size.width);
+ EXPECT_EQ(18u, metro.spriteImage->image.size.height);
EXPECT_EQ(1.0f, metro.spriteImage->pixelRatio);
+ // Now the image was created lazily.
+ EXPECT_EQ(89u, atlas.getAtlasImage().size.width);
+ EXPECT_EQ(157u, atlas.getAtlasImage().size.height);
+
EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlassize.png"),
- imageFromAtlas(atlas));
+ atlas.getAtlasImage());
}
TEST(SpriteAtlas, Updates) {
- SpriteAtlas atlas(32, 32, 1);
+ SpriteAtlas atlas({ 32, 32 }, 1);
EXPECT_EQ(1.0f, atlas.getPixelRatio());
- EXPECT_EQ(32, atlas.getWidth());
- EXPECT_EQ(32, atlas.getHeight());
- EXPECT_EQ(32, atlas.getTextureWidth());
- EXPECT_EQ(32, atlas.getTextureHeight());
+ EXPECT_EQ(32u, atlas.getSize().width);
+ EXPECT_EQ(32u, atlas.getSize().height);
- atlas.setSprite("one", std::make_shared<SpriteImage>(PremultipliedImage(16, 12), 1));
+ atlas.setSprite("one", std::make_shared<SpriteImage>(PremultipliedImage({ 16, 12 }), 1));
auto one = *atlas.getImage("one", SpritePatternMode::Single);
EXPECT_EQ(0, one.pos.x);
EXPECT_EQ(0, one.pos.y);
@@ -135,16 +123,20 @@ TEST(SpriteAtlas, Updates) {
EXPECT_EQ(16, one.pos.h);
EXPECT_EQ(16, one.spriteImage->getWidth());
EXPECT_EQ(12, one.spriteImage->getHeight());
- EXPECT_EQ(16u, one.spriteImage->image.width);
- EXPECT_EQ(12u, one.spriteImage->image.height);
+ EXPECT_EQ(16u, one.spriteImage->image.size.width);
+ EXPECT_EQ(12u, one.spriteImage->image.size.height);
EXPECT_EQ(1.0f, one.spriteImage->pixelRatio);
+ // Now the image was created lazily.
+ EXPECT_EQ(32u, atlas.getAtlasImage().size.width);
+ EXPECT_EQ(32u, atlas.getAtlasImage().size.height);
+
EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas-empty.png"),
- imageFromAtlas(atlas));
+ atlas.getAtlasImage());
// Update sprite
- PremultipliedImage image2(16, 12);
- for (size_t i = 0; i < image2.size(); i++) {
+ PremultipliedImage image2({ 16, 12 });
+ for (size_t i = 0; i < image2.bytes(); i++) {
image2.data.get()[i] = 255;
}
auto newSprite = std::make_shared<SpriteImage>(std::move(image2), 1);
@@ -153,23 +145,23 @@ TEST(SpriteAtlas, Updates) {
// Atlas texture hasn't changed yet.
EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas-empty.png"),
- imageFromAtlas(atlas));
+ atlas.getAtlasImage());
atlas.updateDirty();
// Now the atlas texture has changed.
EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas-updated.png"),
- imageFromAtlas(atlas));
+ atlas.getAtlasImage());
}
TEST(SpriteAtlas, AddRemove) {
FixtureLog log;
- const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
- const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
- const auto sprite3 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
+ const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage({ 16, 16 }), 2);
+ const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage({ 16, 16 }), 2);
+ const auto sprite3 = std::make_shared<SpriteImage>(PremultipliedImage({ 16, 16 }), 2);
- SpriteAtlas atlas(32, 32, 1);
+ SpriteAtlas atlas({ 32, 32 }, 1);
// Adding single
atlas.setSprite("one", sprite1);
@@ -210,19 +202,19 @@ TEST(SpriteAtlas, AddRemove) {
TEST(SpriteAtlas, OtherPixelRatio) {
FixtureLog log;
- const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(8, 8), 1);
+ const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage({ 8, 8 }), 1);
- SpriteAtlas atlas(32, 32, 1);
+ SpriteAtlas atlas({ 32, 32 }, 1);
// Adding mismatched sprite image
atlas.setSprite("one", sprite1);
}
TEST(SpriteAtlas, Multiple) {
- const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
- const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
+ const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage({ 16, 16 }), 2);
+ const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage({ 16, 16 }), 2);
- SpriteAtlas atlas(32, 32, 1);
+ SpriteAtlas atlas({ 32, 32 }, 1);
atlas.setSprites({
{ "one", sprite1 }, { "two", sprite2 },
@@ -232,10 +224,10 @@ TEST(SpriteAtlas, Multiple) {
TEST(SpriteAtlas, Replace) {
FixtureLog log;
- const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
- const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
+ const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage({ 16, 16 }), 2);
+ const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage({ 16, 16 }), 2);
- SpriteAtlas atlas(32, 32, 1);
+ SpriteAtlas atlas({ 32, 32 }, 1);
atlas.setSprite("sprite", sprite1);
EXPECT_EQ(sprite1, atlas.getSprite("sprite"));
@@ -246,12 +238,12 @@ TEST(SpriteAtlas, Replace) {
TEST(SpriteAtlas, ReplaceWithDifferentDimensions) {
FixtureLog log;
- PremultipliedImage image(16, 16);
- PremultipliedImage image2(18, 18);
- const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
- const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage(18, 18), 2);
+ PremultipliedImage image({ 16, 16 });
+ PremultipliedImage image2({ 18, 18 });
+ const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage({ 16, 16 }), 2);
+ const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage({ 18, 18 }), 2);
- SpriteAtlas atlas(32, 32, 1);
+ SpriteAtlas atlas({ 32, 32 }, 1);
atlas.setSprite("sprite", sprite1);
atlas.setSprite("sprite", sprite2);
@@ -273,7 +265,7 @@ public:
util::RunLoop loop;
StubFileSource fileSource;
StubStyleObserver observer;
- SpriteAtlas spriteAtlas { 32, 32, 1 };
+ SpriteAtlas spriteAtlas{ { 32, 32 }, 1 };
void run() {
// Squelch logging.
diff --git a/test/sprite/sprite_image.test.cpp b/test/sprite/sprite_image.test.cpp
index f8982826a3..97a37513ac 100644
--- a/test/sprite/sprite_image.test.cpp
+++ b/test/sprite/sprite_image.test.cpp
@@ -7,7 +7,7 @@
using namespace mbgl;
TEST(Sprite, SpriteImageZeroWidth) {
- PremultipliedImage image(0, 16);
+ PremultipliedImage image({ 0, 16 });
try {
SpriteImage(std::move(image), 2.0);
FAIL() << "Expected exception";
@@ -17,7 +17,7 @@ TEST(Sprite, SpriteImageZeroWidth) {
}
TEST(Sprite, SpriteImageZeroHeight) {
- PremultipliedImage image(16, 0);
+ PremultipliedImage image({ 16, 0 });
try {
SpriteImage(std::move(image), 2.0);
FAIL() << "Expected exception";
@@ -27,7 +27,7 @@ TEST(Sprite, SpriteImageZeroHeight) {
}
TEST(Sprite, SpriteImageZeroRatio) {
- PremultipliedImage image(16, 16);
+ PremultipliedImage image({ 16, 16 });
try {
SpriteImage(std::move(image), 0.0);
FAIL() << "Expected exception";
@@ -37,21 +37,21 @@ TEST(Sprite, SpriteImageZeroRatio) {
}
TEST(Sprite, SpriteImage) {
- PremultipliedImage image(32, 24);
+ PremultipliedImage image({ 32, 24 });
SpriteImage sprite(std::move(image), 2.0);
EXPECT_EQ(16, sprite.getWidth());
- EXPECT_EQ(32u, sprite.image.width);
+ EXPECT_EQ(32u, sprite.image.size.width);
EXPECT_EQ(12, sprite.getHeight());
- EXPECT_EQ(24u, sprite.image.height);
+ EXPECT_EQ(24u, sprite.image.size.height);
EXPECT_EQ(2, sprite.pixelRatio);
}
TEST(Sprite, SpriteImageFractionalRatio) {
- PremultipliedImage image(20, 12);
+ PremultipliedImage image({ 20, 12 });
SpriteImage sprite(std::move(image), 1.5);
EXPECT_EQ(float(20.0 / 1.5), sprite.getWidth());
- EXPECT_EQ(20u, sprite.image.width);
+ EXPECT_EQ(20u, sprite.image.size.width);
EXPECT_EQ(float(12.0 / 1.5), sprite.getHeight());
- EXPECT_EQ(12u, sprite.image.height);
+ EXPECT_EQ(12u, sprite.image.size.height);
EXPECT_EQ(1.5, sprite.pixelRatio);
}
diff --git a/test/sprite/sprite_parser.test.cpp b/test/sprite/sprite_parser.test.cpp
index 8d32d081bf..d634df1c1a 100644
--- a/test/sprite/sprite_parser.test.cpp
+++ b/test/sprite/sprite_parser.test.cpp
@@ -24,8 +24,8 @@ TEST(Sprite, SpriteImageCreationInvalid) {
const PremultipliedImage image_1x = decodeImage(util::read_file("test/fixtures/annotations/emerald.png"));
- ASSERT_EQ(200u, image_1x.width);
- ASSERT_EQ(299u, image_1x.height);
+ ASSERT_EQ(200u, image_1x.size.width);
+ ASSERT_EQ(299u, image_1x.size.height);
ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 0, 16, 1, false)); // width == 0
ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, 0, 1, false)); // height == 0
@@ -38,30 +38,115 @@ TEST(Sprite, SpriteImageCreationInvalid) {
ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, 1025, 1, false)); // too tall
ASSERT_EQ(nullptr, createSpriteImage(image_1x, -1, 0, 16, 16, 1, false)); // srcX < 0
ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, -1, 16, 16, 1, false)); // srcY < 0
- ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, image_1x.width + 1, 16, 1, false)); // right edge out of bounds
- ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, image_1x.height + 1, 1, false)); // bottom edge out of bounds
+ ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, image_1x.size.width + 1, 16, 1, false)); // right edge out of bounds
+ ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, image_1x.size.height + 1, 1, false)); // bottom edge out of bounds
- EXPECT_EQ(13u, log.count({
+ EXPECT_EQ(1u, log.count({
+ EventSeverity::Error,
+ Event::Sprite,
+ int64_t(-1),
+ "Can't create sprite with invalid metrics: 0x16@0,0 in 200x299@1x sprite",
+ }));
+
+ EXPECT_EQ(1u, log.count({
+ EventSeverity::Error,
+ Event::Sprite,
+ int64_t(-1),
+ "Can't create sprite with invalid metrics: 16x0@0,0 in 200x299@1x sprite",
+ }));
+
+ EXPECT_EQ(1u, log.count({
+ EventSeverity::Error,
+ Event::Sprite,
+ int64_t(-1),
+ "Can't create sprite with invalid metrics: 4294967295x16@0,0 in 200x299@1x sprite",
+ }));
+
+ EXPECT_EQ(1u, log.count({
+ EventSeverity::Error,
+ Event::Sprite,
+ int64_t(-1),
+ "Can't create sprite with invalid metrics: 16x4294967295@0,0 in 200x299@1x sprite",
+ }));
+
+ EXPECT_EQ(1u, log.count({
+ EventSeverity::Error,
+ Event::Sprite,
+ int64_t(-1),
+ "Can't create sprite with invalid metrics: 1x1@0,0 in 200x299@0x sprite",
+ }));
+
+ EXPECT_EQ(1u, log.count({
+ EventSeverity::Error,
+ Event::Sprite,
+ int64_t(-1),
+ "Can't create sprite with invalid metrics: 1x1@0,0 in 200x299@-1x sprite",
+ }));
+
+ EXPECT_EQ(1u, log.count({
EventSeverity::Error,
Event::Sprite,
int64_t(-1),
- "Can't create sprite with invalid metrics",
+ "Can't create sprite with invalid metrics: 1x1@0,0 in 200x299@23x sprite",
}));
+
+ EXPECT_EQ(1u, log.count({
+ EventSeverity::Error,
+ Event::Sprite,
+ int64_t(-1),
+ "Can't create sprite with invalid metrics: 2048x16@0,0 in 200x299@1x sprite",
+ }));
+
+ EXPECT_EQ(1u, log.count({
+ EventSeverity::Error,
+ Event::Sprite,
+ int64_t(-1),
+ "Can't create sprite with invalid metrics: 16x1025@0,0 in 200x299@1x sprite",
+ }));
+
+ EXPECT_EQ(1u, log.count({
+ EventSeverity::Error,
+ Event::Sprite,
+ int64_t(-1),
+ "Can't create sprite with invalid metrics: 16x16@4294967295,0 in 200x299@1x sprite",
+ }));
+
+ EXPECT_EQ(1u, log.count({
+ EventSeverity::Error,
+ Event::Sprite,
+ int64_t(-1),
+ "Can't create sprite with invalid metrics: 16x16@0,4294967295 in 200x299@1x sprite",
+ }));
+
+ EXPECT_EQ(1u, log.count({
+ EventSeverity::Error,
+ Event::Sprite,
+ int64_t(-1),
+ "Can't create sprite with invalid metrics: 201x16@0,0 in 200x299@1x sprite",
+ }));
+
+ EXPECT_EQ(1u, log.count({
+ EventSeverity::Error,
+ Event::Sprite,
+ int64_t(-1),
+ "Can't create sprite with invalid metrics: 16x300@0,0 in 200x299@1x sprite",
+ }));
+
}
TEST(Sprite, SpriteImageCreation1x) {
const PremultipliedImage image_1x = decodeImage(util::read_file("test/fixtures/annotations/emerald.png"));
- ASSERT_EQ(200u, image_1x.width);
- ASSERT_EQ(299u, image_1x.height);
+ ASSERT_EQ(200u, image_1x.size.width);
+ ASSERT_EQ(299u, image_1x.size.height);
{ // "museum_icon":{"x":177,"y":187,"width":18,"height":18,"pixelRatio":1,"sdf":false}
const auto sprite = createSpriteImage(image_1x, 177, 187, 18, 18, 1, false);
ASSERT_TRUE(sprite.get());
EXPECT_EQ(18, sprite->getWidth());
EXPECT_EQ(18, sprite->getHeight());
- EXPECT_EQ(18u, sprite->image.width);
- EXPECT_EQ(18u, sprite->image.height);
+ EXPECT_EQ(18u, sprite->image.size.width);
+ EXPECT_EQ(18u, sprite->image.size.height);
EXPECT_EQ(1, sprite->pixelRatio);
EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteimagecreation1x-museum.png"),
sprite->image);
@@ -76,8 +161,8 @@ TEST(Sprite, SpriteImageCreation2x) {
ASSERT_TRUE(sprite.get());
EXPECT_EQ(18, sprite->getWidth());
EXPECT_EQ(18, sprite->getHeight());
- EXPECT_EQ(36u, sprite->image.width);
- EXPECT_EQ(36u, sprite->image.height);
+ EXPECT_EQ(36u, sprite->image.size.width);
+ EXPECT_EQ(36u, sprite->image.size.height);
EXPECT_EQ(2, sprite->pixelRatio);
EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteimagecreation2x.png"),
sprite->image);
@@ -91,8 +176,8 @@ TEST(Sprite, SpriteImageCreation1_5x) {
ASSERT_TRUE(sprite.get());
EXPECT_EQ(24, sprite->getWidth());
EXPECT_EQ(24, sprite->getHeight());
- EXPECT_EQ(36u, sprite->image.width);
- EXPECT_EQ(36u, sprite->image.height);
+ EXPECT_EQ(36u, sprite->image.size.width);
+ EXPECT_EQ(36u, sprite->image.size.height);
EXPECT_EQ(1.5, sprite->pixelRatio);
EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteimagecreation1_5x-museum.png"),
sprite->image);
@@ -102,8 +187,8 @@ TEST(Sprite, SpriteImageCreation1_5x) {
ASSERT_TRUE(sprite2.get());
EXPECT_EQ(float(35 / 1.5), sprite2->getWidth());
EXPECT_EQ(float(35 / 1.5), sprite2->getHeight());
- EXPECT_EQ(35u, sprite2->image.width);
- EXPECT_EQ(35u, sprite2->image.height);
+ EXPECT_EQ(35u, sprite2->image.size.width);
+ EXPECT_EQ(35u, sprite2->image.size.height);
EXPECT_EQ(1.5, sprite2->pixelRatio);
EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteimagecreation1_5x-hospital.png"),
sprite2->image);
@@ -198,8 +283,8 @@ TEST(Sprite, SpriteParsing) {
auto sprite = images.find("generic-metro")->second;
EXPECT_EQ(18, sprite->getWidth());
EXPECT_EQ(18, sprite->getHeight());
- EXPECT_EQ(18u, sprite->image.width);
- EXPECT_EQ(18u, sprite->image.height);
+ EXPECT_EQ(18u, sprite->image.size.width);
+ EXPECT_EQ(18u, sprite->image.size.height);
EXPECT_EQ(1, sprite->pixelRatio);
EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteparsing.png"), sprite->image);
}
@@ -228,7 +313,7 @@ TEST(Sprite, SpriteParsingEmptyImage) {
EventSeverity::Error,
Event::Sprite,
int64_t(-1),
- "Can't create sprite with invalid metrics",
+ "Can't create sprite with invalid metrics: 0x0@0,0 in 200x299@1x sprite",
}));
}
@@ -261,7 +346,7 @@ TEST(Sprite, SpriteParsingWidthTooBig) {
EventSeverity::Error,
Event::Sprite,
int64_t(-1),
- "Can't create sprite with invalid metrics",
+ "Can't create sprite with invalid metrics: 0x32@0,0 in 200x299@1x sprite",
}));
}
@@ -284,7 +369,7 @@ TEST(Sprite, SpriteParsingNegativeWidth) {
EventSeverity::Error,
Event::Sprite,
int64_t(-1),
- "Can't create sprite with invalid metrics",
+ "Can't create sprite with invalid metrics: 0x32@0,0 in 200x299@1x sprite",
}));
}
@@ -301,6 +386,6 @@ TEST(Sprite, SpriteParsingNullRatio) {
EventSeverity::Error,
Event::Sprite,
int64_t(-1),
- "Can't create sprite with invalid metrics",
+ "Can't create sprite with invalid metrics: 32x32@0,0 in 200x299@0x sprite",
}));
}
diff --git a/test/src/mbgl/test/conversion_stubs.hpp b/test/src/mbgl/test/conversion_stubs.hpp
index b80a2c98bd..ddffb1e3b2 100644
--- a/test/src/mbgl/test/conversion_stubs.hpp
+++ b/test/src/mbgl/test/conversion_stubs.hpp
@@ -104,7 +104,7 @@ inline optional<mbgl::Value> toValue(const Value& value) {
} else if (value.is<std::string>()) {
return { value.get<std::string>() };
} else if (value.is<float>()) {
- return { value.get<float>() };
+ return { double(value.get<float>()) };
} else {
return {};
}
diff --git a/test/src/mbgl/test/fixture_log_observer.hpp b/test/src/mbgl/test/fixture_log_observer.hpp
index 918bbee18c..96ddc2c54f 100644
--- a/test/src/mbgl/test/fixture_log_observer.hpp
+++ b/test/src/mbgl/test/fixture_log_observer.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <vector>
#include <cstdarg>
diff --git a/test/src/mbgl/test/stub_tile_observer.hpp b/test/src/mbgl/test/stub_tile_observer.hpp
new file mode 100644
index 0000000000..43ae4d8360
--- /dev/null
+++ b/test/src/mbgl/test/stub_tile_observer.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <mbgl/tile/tile_observer.hpp>
+
+using namespace mbgl;
+
+/**
+ * An implementation of TileObserver that forwards all methods to dynamically-settable lambas.
+ */
+class StubTileObserver : public TileObserver {
+public:
+ void onTileChanged(Tile& tile) override {
+ if (tileChanged) tileChanged(tile);
+ }
+
+ void onTileError(Tile& tile, std::exception_ptr error) override {
+ if (tileError) tileError(tile, error);
+ }
+
+ std::function<void (Tile&)> tileChanged;
+ std::function<void (Tile&, std::exception_ptr)> tileError;
+};
diff --git a/test/src/mbgl/test/util.cpp b/test/src/mbgl/test/util.cpp
index 7f98c43dc9..7ca2d72504 100644
--- a/test/src/mbgl/test/util.cpp
+++ b/test/src/mbgl/test/util.cpp
@@ -1,8 +1,9 @@
#include <mbgl/test/util.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
+#include <mbgl/gl/headless_display.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/chrono.hpp>
@@ -98,13 +99,18 @@ Server::~Server() {
}
}
+std::shared_ptr<HeadlessDisplay> sharedDisplay() {
+ static auto display = std::make_shared<HeadlessDisplay>();
+ return display;
+}
+
PremultipliedImage render(Map& map, OffscreenView& view) {
PremultipliedImage result;
map.renderStill(view, [&](std::exception_ptr) {
result = view.readStillImage();
});
- while (!result.size()) {
+ while (!result.valid()) {
util::RunLoop::Get()->runOnce();
}
@@ -132,24 +138,23 @@ void checkImage(const std::string& base,
}
PremultipliedImage expected = decodeImage(expected_image);
- PremultipliedImage diff { expected.width, expected.height };
+ PremultipliedImage diff { expected.size };
#if !TEST_READ_ONLY
util::write_file(base + "/actual.png", encodePNG(actual));
#endif
- ASSERT_EQ(expected.width, actual.width);
- ASSERT_EQ(expected.height, actual.height);
+ ASSERT_EQ(expected.size, actual.size);
double pixels = mapbox::pixelmatch(actual.data.get(),
expected.data.get(),
- expected.width,
- expected.height,
+ expected.size.width,
+ expected.size.height,
diff.data.get(),
pixelThreshold);
- EXPECT_LE(pixels / (expected.width * expected.height), imageThreshold);
+ EXPECT_LE(pixels / (expected.size.width * expected.size.height), imageThreshold);
#if !TEST_READ_ONLY
util::write_file(base + "/diff.png", encodePNG(diff));
diff --git a/test/src/mbgl/test/util.hpp b/test/src/mbgl/test/util.hpp
index b8ecf175aa..34d8969d3c 100644
--- a/test/src/mbgl/test/util.hpp
+++ b/test/src/mbgl/test/util.hpp
@@ -4,7 +4,10 @@
#include <TargetConditionals.h>
#endif
-#if TARGET_OS_IOS
+#if __ANDROID__
+#define TEST_READ_ONLY 0
+#define TEST_HAS_SERVER 0
+#elif TARGET_OS_IOS
#define TEST_READ_ONLY 1
#define TEST_HAS_SERVER 0
#else
@@ -46,6 +49,7 @@
#include <mbgl/util/chrono.hpp>
#include <cstdint>
+#include <memory>
#include <gtest/gtest.h>
@@ -53,6 +57,7 @@ namespace mbgl {
class Map;
class OffscreenView;
+class HeadlessDisplay;
namespace test {
@@ -65,6 +70,8 @@ private:
int fd = -1;
};
+std::shared_ptr<HeadlessDisplay> sharedDisplay();
+
PremultipliedImage render(Map&, OffscreenView&);
void checkImage(const std::string& base,
diff --git a/test/storage/asset_file_source.test.cpp b/test/storage/asset_file_source.test.cpp
index ab214ff793..7e634fc68e 100644
--- a/test/storage/asset_file_source.test.cpp
+++ b/test/storage/asset_file_source.test.cpp
@@ -1,5 +1,5 @@
#include <mbgl/storage/asset_file_source.hpp>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/platform.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/thread.hpp>
@@ -27,7 +27,7 @@ TEST(AssetFileSource, Load) {
AssetFileSource fs(getFileSourceRoot());
// iOS seems to run out of file descriptors...
-#if TARGET_OS_IPHONE
+#if TARGET_OS_IPHONE || __ANDROID__
unsigned numThreads = 30;
#else
unsigned numThreads = 50;
diff --git a/test/storage/local_file_source.test.cpp b/test/storage/local_file_source.test.cpp
index afb418d735..c2f04d7543 100644
--- a/test/storage/local_file_source.test.cpp
+++ b/test/storage/local_file_source.test.cpp
@@ -1,5 +1,5 @@
#include <mbgl/storage/local_file_source.hpp>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/platform.hpp>
#include <mbgl/util/run_loop.hpp>
#include <unistd.h>
diff --git a/test/storage/online_file_source.test.cpp b/test/storage/online_file_source.test.cpp
index 95b330390f..966ef6239a 100644
--- a/test/storage/online_file_source.test.cpp
+++ b/test/storage/online_file_source.test.cpp
@@ -149,7 +149,7 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(RetryDelayOnExpiredTile)) {
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
counter++;
EXPECT_EQ(nullptr, res.error);
- EXPECT_GT(util::now(), res.expires);
+ EXPECT_GT(util::now(), *res.expires);
});
util::Timer timer;
@@ -173,14 +173,14 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(RetryOnClockSkew)) {
switch (counter++) {
case 0: {
EXPECT_EQ(nullptr, res.error);
- EXPECT_GT(util::now(), res.expires);
+ EXPECT_GT(util::now(), *res.expires);
} break;
case 1: {
EXPECT_EQ(nullptr, res.error);
auto now = util::now();
- EXPECT_LT(now + Seconds(40), res.expires) << "Expiration not interpolated to 60s";
- EXPECT_GT(now + Seconds(80), res.expires) << "Expiration not interpolated to 60s";
+ EXPECT_LT(now + Seconds(40), *res.expires) << "Expiration not interpolated to 60s";
+ EXPECT_GT(now + Seconds(80), *res.expires) << "Expiration not interpolated to 60s";
loop.stop();
} break;
@@ -413,4 +413,4 @@ TEST(OnlineFileSource, ChangeAPIBaseURL){
const std::string customURL = "test.domain";
fs.setAPIBaseURL(customURL);
EXPECT_EQ(customURL, fs.getAPIBaseURL());
-} \ No newline at end of file
+}
diff --git a/test/style/conversion/function.test.cpp b/test/style/conversion/function.test.cpp
new file mode 100644
index 0000000000..e93207ea13
--- /dev/null
+++ b/test/style/conversion/function.test.cpp
@@ -0,0 +1,54 @@
+#include <mbgl/test/util.hpp>
+
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/rapidjson_conversion.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/function.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+using namespace mbgl;
+using namespace mbgl::style;
+using namespace mbgl::style::conversion;
+
+auto parseFunction(const std::string& src) {
+ JSDocument doc;
+ doc.Parse<0>(src);
+ return convert<Function<float>>(doc);
+}
+
+TEST(StyleConversion, Function) {
+ auto fn1 = parseFunction("{\"stops\":[]}");
+ ASSERT_FALSE(fn1);
+ ASSERT_EQ("function must have at least one stop", fn1.error().message);
+
+ auto fn2 = parseFunction("{\"stops\":[1]}");
+ ASSERT_FALSE(fn2);
+ ASSERT_EQ("function stop must be an array", fn2.error().message);
+
+ auto fn3 = parseFunction("{\"stops\":[[]]}");
+ ASSERT_FALSE(fn3);
+ ASSERT_EQ("function stop must have two elements", fn3.error().message);
+
+ auto fn4 = parseFunction("{\"stops\":[[-1,-1]]}");
+ ASSERT_TRUE(bool(fn4));
+
+ auto fn5 = parseFunction("{\"stops\":[[0,1,2]]}");
+ ASSERT_FALSE(fn5);
+ ASSERT_EQ("function stop must have two elements", fn5.error().message);
+
+ auto fn6 = parseFunction("{\"stops\":[[0,\"x\"]]}");
+ ASSERT_FALSE(fn6);
+ ASSERT_EQ("value must be a number", fn6.error().message);
+
+ auto fn7 = parseFunction("{}");
+ ASSERT_FALSE(fn7);
+ ASSERT_EQ("function value must specify stops", fn7.error().message);
+
+ auto fn8 = parseFunction("[]");
+ ASSERT_FALSE(fn8);
+ ASSERT_EQ("function must be an object", fn8.error().message);
+
+ auto fn9 = parseFunction("{\"stops\":[[0,0]],\"base\":false}");
+ ASSERT_FALSE(fn9);
+ ASSERT_EQ("function base must be a number", fn9.error().message);
+}
diff --git a/test/style/conversion/geojson_options.test.cpp b/test/style/conversion/geojson_options.test.cpp
index 46a2aa950b..14a7adbba7 100644
--- a/test/style/conversion/geojson_options.test.cpp
+++ b/test/style/conversion/geojson_options.test.cpp
@@ -4,7 +4,7 @@
#include <mbgl/style/conversion/geojson_options.hpp>
#include <mbgl/test/conversion_stubs.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
using namespace mbgl::style;
using namespace mbgl::style::conversion;
@@ -17,7 +17,7 @@ TEST(GeoJSONOptions, Basic) {
}
TEST(GeoJSONOptions, ErrorHandling) {
- ValueMap map {{"maxzoom", "should not be a string"}};
+ ValueMap map {{"maxzoom", std::string{"should not be a string"}}};
Value raw(map);
Result<GeoJSONOptions> converted = convert<GeoJSONOptions>(raw);
ASSERT_FALSE((bool) converted);
@@ -44,14 +44,14 @@ TEST(GeoJSONOptions, RetainsDefaults) {
TEST(GeoJSONOptions, FullConversion) {
ValueMap map {
//GeoJSON-VT
- {"maxzoom", 1},
- {"buffer", 2},
- {"tolerance", 3},
+ {"maxzoom", 1.0f},
+ {"buffer", 2.0f},
+ {"tolerance", 3.0f},
//Supercluster
{"cluster", true},
- {"clusterRadius", 4},
- {"clusterMaxZoom", 5}
+ {"clusterRadius", 4.0f},
+ {"clusterMaxZoom", 5.0f}
};
Value raw(map);
GeoJSONOptions converted = *convert<GeoJSONOptions>(raw);
diff --git a/test/style/conversion/stringify.test.cpp b/test/style/conversion/stringify.test.cpp
new file mode 100644
index 0000000000..be5d65d4ce
--- /dev/null
+++ b/test/style/conversion/stringify.test.cpp
@@ -0,0 +1,98 @@
+#include <mbgl/test/util.hpp>
+
+#include <mbgl/style/conversion/stringify.hpp>
+#include <mbgl/style/types.hpp>
+#include <mbgl/style/layers/symbol_layer_properties.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+#include <rapidjson/writer.h>
+#include <rapidjson/stringbuffer.h>
+
+using namespace mbgl;
+using namespace mbgl::style;
+using namespace mbgl::style::conversion;
+
+template <class T>
+std::string stringify(const T& t) {
+ rapidjson::StringBuffer s;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(s);
+ stringify(writer, t);
+ return s.GetString();
+}
+
+TEST(Stringify, NullValue) {
+ ASSERT_EQ(stringify(NullValue()), "null");
+}
+
+TEST(Stringify, Boolean) {
+ ASSERT_EQ(stringify(true), "true");
+ ASSERT_EQ(stringify(false), "false");
+}
+
+TEST(Stringify, Uint64) {
+ ASSERT_EQ(stringify(uint64_t(0)), "0");
+ ASSERT_EQ(stringify(uint64_t(1)), "1");
+}
+
+TEST(Stringify, Int64) {
+ ASSERT_EQ(stringify(int64_t(0)), "0");
+ ASSERT_EQ(stringify(int64_t(-1)), "-1");
+}
+
+TEST(Stringify, Double) {
+ ASSERT_EQ(stringify(0.0), "0.0");
+ ASSERT_EQ(stringify(10.1234), "10.1234");
+}
+
+TEST(Stringify, String) {
+ ASSERT_EQ(stringify(std::string("test")), "\"test\"");
+}
+
+TEST(Stringify, Enum) {
+ ASSERT_EQ(stringify(VisibilityType::Visible), "\"visible\"");
+}
+
+TEST(Stringify, Color) {
+ ASSERT_EQ(stringify(Color::blue()), "\"rgba(0,0,255,1)\"");
+}
+
+TEST(Stringify, Array) {
+ ASSERT_EQ(stringify(std::array<float, 2> {{ 1, 2 }}), "[1.0,2.0]");
+}
+
+TEST(Stringify, Vector) {
+ ASSERT_EQ(stringify(std::vector<float> {{ 1, 2 }}), "[1.0,2.0]");
+}
+
+TEST(Stringify, Map) {
+ ASSERT_EQ(stringify(std::unordered_map<std::string, float> {{ "a", 1 }}), "{\"a\":1.0}");
+}
+
+TEST(Stringify, Value) {
+ ASSERT_EQ(stringify(Value(true)), "true");
+ ASSERT_EQ(stringify(Value(uint64_t(0))), "0");
+ ASSERT_EQ(stringify(Value(1.2)), "1.2");
+}
+
+TEST(Stringify, Filter) {
+ ASSERT_EQ(stringify(NullFilter()), "null");
+ ASSERT_EQ(stringify(EqualsFilter { "a", 1.0 }), "[\"==\",\"a\",1.0]");
+}
+
+TEST(Stringify, Function) {
+ ASSERT_EQ(stringify(Function<float>({{0, 1}}, 2)), "{\"base\":2.0,\"stops\":[[0.0,1.0]]}");
+}
+
+TEST(Stringify, PropertyValue) {
+ ASSERT_EQ(stringify(PropertyValue<float>(1)), "1.0");
+ ASSERT_EQ(stringify(PropertyValue<float>(Function<float>({{0, 1}}, 2))), "{\"base\":2.0,\"stops\":[[0.0,1.0]]}");
+}
+
+TEST(Stringify, Layout) {
+ ASSERT_EQ(stringify(SymbolLayoutProperties()), "{}");
+
+ SymbolLayoutProperties layout;
+ layout.unevaluated.get<SymbolAvoidEdges>() = true;
+ layout.unevaluated.get<IconPadding>() = 2.0;
+ ASSERT_EQ(stringify(layout), "{\"symbol-avoid-edges\":true,\"icon-padding\":2.0}");
+}
diff --git a/test/style/filter.test.cpp b/test/style/filter.test.cpp
index b49f424a39..33b64978f5 100644
--- a/test/style/filter.test.cpp
+++ b/test/style/filter.test.cpp
@@ -42,7 +42,7 @@ TEST(Filter, EqualsNumber) {
ASSERT_FALSE(f(feature({{ "foo", std::string("0") }})));
ASSERT_FALSE(f(feature({{ "foo", false }})));
ASSERT_FALSE(f(feature({{ "foo", true }})));
- ASSERT_FALSE(f(feature({{ "foo", nullptr }})));
+ ASSERT_FALSE(f(feature({{ "foo", mapbox::geometry::null_value }})));
ASSERT_FALSE(f(feature({{}})));
}
@@ -113,13 +113,13 @@ TEST(Filter, NotHas) {
TEST(Filter, ID) {
Feature feature1 { Point<double>() };
- feature1.id = { 1234 };
+ feature1.id = { uint64_t(1234) };
ASSERT_TRUE(parse("[\"==\", \"$id\", 1234]")(feature1));
ASSERT_FALSE(parse("[\"==\", \"$id\", \"1234\"]")(feature1));
Feature feature2 { Point<double>() };
- feature2.properties["id"] = { 1234 };
+ feature2.properties["id"] = { uint64_t(1234) };
ASSERT_FALSE(parse("[\"==\", \"$id\", 1234]")(feature2));
}
diff --git a/test/style/functions.test.cpp b/test/style/functions.test.cpp
index 9577bcc633..8553d13349 100644
--- a/test/style/functions.test.cpp
+++ b/test/style/functions.test.cpp
@@ -2,28 +2,31 @@
#include <mbgl/test/util.hpp>
#include <mbgl/style/property_evaluator.hpp>
-#include <mbgl/style/calculation_parameters.hpp>
+#include <mbgl/style/property_evaluation_parameters.hpp>
using namespace mbgl;
using namespace mbgl::style;
float evaluate(PropertyValue<float> value, float zoom) {
- return PropertyValue<float>::visit(value, PropertyEvaluator<float>(CalculationParameters(zoom), 0));
+ return value.evaluate(PropertyEvaluator<float>(PropertyEvaluationParameters(zoom), 0));
}
std::string evaluate(PropertyValue<std::string> value, float zoom) {
- return PropertyValue<std::string>::visit(value, PropertyEvaluator<std::string>(CalculationParameters(zoom), ""));
+ return value.evaluate(PropertyEvaluator<std::string>(PropertyEvaluationParameters(zoom), ""));
+}
+bool evaluate(PropertyValue<bool> value, float zoom) {
+ return value.evaluate(PropertyEvaluator<bool>(PropertyEvaluationParameters(zoom), false));
}
TEST(Function, Constant) {
- EXPECT_EQ(2.0f, evaluate(2, 0));
- EXPECT_EQ(3.8f, evaluate(3.8, 0));
- EXPECT_EQ(22.0f, evaluate(22, 0));
- EXPECT_EQ(2.0f, evaluate(2, 4));
- EXPECT_EQ(3.8f, evaluate(3.8, 4));
- EXPECT_EQ(22.0f, evaluate(22, 4));
- EXPECT_EQ(2.0f, evaluate(2, 22));
- EXPECT_EQ(3.8f, evaluate(3.8, 22));
- EXPECT_EQ(22.0f, evaluate(22, 22));
+ EXPECT_EQ(2.0f, evaluate(PropertyValue<float>(2.0), 0));
+ EXPECT_EQ(3.8f, evaluate(PropertyValue<float>(3.8), 0));
+ EXPECT_EQ(22.0f, evaluate(PropertyValue<float>(22.0), 0));
+ EXPECT_EQ(2.0f, evaluate(PropertyValue<float>(2.0), 4));
+ EXPECT_EQ(3.8f, evaluate(PropertyValue<float>(3.8), 4));
+ EXPECT_EQ(22.0f, evaluate(PropertyValue<float>(22.0), 4));
+ EXPECT_EQ(2.0f, evaluate(PropertyValue<float>(2.0), 22));
+ EXPECT_EQ(3.8f, evaluate(PropertyValue<float>(3.8), 22));
+ EXPECT_EQ(22.0f, evaluate(PropertyValue<float>(22.0), 22));
}
TEST(Function, Stops) {
@@ -50,12 +53,6 @@ TEST(Function, Stops) {
EXPECT_EQ(3.0, evaluate(slope_2, 15));
EXPECT_EQ(3.0, evaluate(slope_2, 22));
- // Test no values.
- Function<float> slope_3({}, 1.75);
- EXPECT_EQ(1, evaluate(slope_3, 2));
- EXPECT_EQ(1, evaluate(slope_3, 6));
- EXPECT_EQ(1, evaluate(slope_3, 12));
-
// Explicit constant slope in fringe regions.
Function<float> slope_4({ { 0, 2 }, { 8, 10 } }, 1);
@@ -66,10 +63,17 @@ TEST(Function, Stops) {
EXPECT_EQ(10, evaluate(slope_4, 8));
// discrete values
- Function<std::string> discrete_0({{ 3, "string0"}, {6, "string1"}, {9, "string2"}}, 1);
+ Function<std::string> discrete_0({{3, "string0"}, {6, "string1"}, {9, "string2"}}, 1);
EXPECT_EQ("string0", evaluate(discrete_0, 2));
EXPECT_EQ("string0", evaluate(discrete_0, 4));
EXPECT_EQ("string1", evaluate(discrete_0, 7));
EXPECT_EQ("string2", evaluate(discrete_0, 9));
EXPECT_EQ("string2", evaluate(discrete_0, 10));
+
+ Function<bool> discreteBool({{1, false}, {3, true}}, 1);
+ EXPECT_FALSE(evaluate(discreteBool, 0));
+ EXPECT_FALSE(evaluate(discreteBool, 1));
+ EXPECT_FALSE(evaluate(discreteBool, 2));
+ EXPECT_TRUE(evaluate(discreteBool, 3));
+ EXPECT_TRUE(evaluate(discreteBool, 4));
}
diff --git a/test/style/group_by_layout.test.cpp b/test/style/group_by_layout.test.cpp
new file mode 100644
index 0000000000..600ba6a0f1
--- /dev/null
+++ b/test/style/group_by_layout.test.cpp
@@ -0,0 +1,44 @@
+#include <mbgl/test/util.hpp>
+
+#include <mbgl/style/group_by_layout.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+
+using namespace mbgl;
+using namespace mbgl::style;
+
+TEST(GroupByLayout, Related) {
+ std::vector<std::unique_ptr<Layer>> layers;
+ layers.push_back(std::make_unique<LineLayer>("a", "source"));
+ layers.push_back(std::make_unique<LineLayer>("b", "source"));
+ auto result = groupByLayout(layers);
+ ASSERT_EQ(1u, result.size());
+ ASSERT_EQ(2u, result[0].size());
+}
+
+TEST(GroupByLayout, UnrelatedType) {
+ std::vector<std::unique_ptr<Layer>> layers;
+ layers.push_back(std::make_unique<BackgroundLayer>("background"));
+ layers.push_back(std::make_unique<CircleLayer>("circle", "source"));
+ auto result = groupByLayout(layers);
+ ASSERT_EQ(2u, result.size());
+}
+
+TEST(GroupByLayout, UnrelatedFilter) {
+ std::vector<std::unique_ptr<Layer>> layers;
+ layers.push_back(std::make_unique<LineLayer>("a", "source"));
+ layers.push_back(std::make_unique<LineLayer>("b", "source"));
+ layers[0]->as<LineLayer>()->setFilter(EqualsFilter());
+ auto result = groupByLayout(layers);
+ ASSERT_EQ(2u, result.size());
+}
+
+TEST(GroupByLayout, UnrelatedLayout) {
+ std::vector<std::unique_ptr<Layer>> layers;
+ layers.push_back(std::make_unique<LineLayer>("a", "source"));
+ layers.push_back(std::make_unique<LineLayer>("b", "source"));
+ layers[0]->as<LineLayer>()->setLineCap(LineCapType::Square);
+ auto result = groupByLayout(layers);
+ ASSERT_EQ(2u, result.size());
+}
diff --git a/test/style/source.test.cpp b/test/style/source.test.cpp
index 73908a144b..01f54d6b18 100644
--- a/test/style/source.test.cpp
+++ b/test/style/source.test.cpp
@@ -11,8 +11,8 @@
#include <mbgl/util/string.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/tileset.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/map/transform.hpp>
#include <mbgl/style/style.hpp>
@@ -50,7 +50,7 @@ public:
// Squelch logging.
Log::setObserver(std::make_unique<Log::NullObserver>());
- transform.resize({{ 512, 512 }});
+ transform.resize({ 512, 512 });
transform.setLatLngZoom({0, 0}, 0);
transformState = transform.getState();
diff --git a/test/text/glyph_atlas.test.cpp b/test/text/glyph_atlas.test.cpp
index 8634cbe913..020a7140cb 100644
--- a/test/text/glyph_atlas.test.cpp
+++ b/test/text/glyph_atlas.test.cpp
@@ -7,7 +7,7 @@
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/io.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
using namespace mbgl;
@@ -16,7 +16,7 @@ public:
util::RunLoop loop;
StubFileSource fileSource;
StubStyleObserver observer;
- GlyphAtlas glyphAtlas { 32, 32, fileSource };
+ GlyphAtlas glyphAtlas{ { 32, 32 }, fileSource };
void run(const std::string& url, const FontStack& fontStack, const GlyphRangeSet& glyphRanges) {
// Squelch logging.
diff --git a/test/text/quads.test.cpp b/test/text/quads.test.cpp
index 421d2f362d..c20218a82f 100644
--- a/test/text/quads.test.cpp
+++ b/test/text/quads.test.cpp
@@ -10,7 +10,7 @@ using namespace mbgl;
using namespace mbgl::style;
TEST(getIconQuads, normal) {
- SymbolLayoutProperties layout;
+ SymbolLayoutProperties::Evaluated layout;
Anchor anchor(2.0, 3.0, 0.0, 0.5f, 0);
SpriteAtlasElement image = {
Rect<uint16_t>( 0, 0, 15, 11 ),
@@ -58,7 +58,7 @@ TEST(getIconQuads, style) {
// none
{
- SymbolLayoutProperties layout;
+ SymbolLayoutProperties::Evaluated layout;
SymbolQuads quads =
getIconQuads(anchor, shapedIcon, line, layout, SymbolPlacementType::Point, shapedText);
@@ -80,9 +80,9 @@ TEST(getIconQuads, style) {
// width
{
- SymbolLayoutProperties layout;
- layout.textSize = LayoutProperty<float>(24.0f);
- layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Width);
+ SymbolLayoutProperties::Evaluated layout;
+ layout.get<TextSize>() = 24.0f;
+ layout.get<IconTextFit>() = IconTextFitType::Width;
SymbolQuads quads =
getIconQuads(anchor, shapedIcon, line, layout, SymbolPlacementType::Point, shapedText);
@@ -98,9 +98,9 @@ TEST(getIconQuads, style) {
// width x textSize
{
- SymbolLayoutProperties layout;
- layout.textSize = LayoutProperty<float>(12.0f);
- layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Width);
+ SymbolLayoutProperties::Evaluated layout;
+ layout.get<TextSize>() = 12.0f;
+ layout.get<IconTextFit>() = IconTextFitType::Width;
SymbolQuads quads =
getIconQuads(anchor, shapedIcon, line, layout, SymbolPlacementType::Point, shapedText);
@@ -116,13 +116,13 @@ TEST(getIconQuads, style) {
// width x textSize + padding
{
- SymbolLayoutProperties layout;
- layout.textSize = LayoutProperty<float>(12.0f);
- layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Width);
- layout.iconTextFitPadding.value[0] = 5.0f;
- layout.iconTextFitPadding.value[1] = 10.0f;
- layout.iconTextFitPadding.value[2] = 5.0f;
- layout.iconTextFitPadding.value[3] = 10.0f;
+ SymbolLayoutProperties::Evaluated layout;
+ layout.get<TextSize>() = 12.0f;
+ layout.get<IconTextFit>() = IconTextFitType::Width;
+ layout.get<IconTextFitPadding>()[0] = 5.0f;
+ layout.get<IconTextFitPadding>()[1] = 10.0f;
+ layout.get<IconTextFitPadding>()[2] = 5.0f;
+ layout.get<IconTextFitPadding>()[3] = 10.0f;
SymbolQuads quads =
getIconQuads(anchor, shapedIcon, line, layout, SymbolPlacementType::Point, shapedText);
@@ -138,9 +138,9 @@ TEST(getIconQuads, style) {
// height
{
- SymbolLayoutProperties layout;
- layout.textSize = LayoutProperty<float>(24.0f);
- layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Height);
+ SymbolLayoutProperties::Evaluated layout;
+ layout.get<TextSize>() = 24.0f;
+ layout.get<IconTextFit>() = IconTextFitType::Height;
SymbolQuads quads =
getIconQuads(anchor, shapedIcon, line, layout, SymbolPlacementType::Point, shapedText);
@@ -156,9 +156,9 @@ TEST(getIconQuads, style) {
// height x textSize
{
- SymbolLayoutProperties layout;
- layout.textSize = LayoutProperty<float>(12.0f);
- layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Height);
+ SymbolLayoutProperties::Evaluated layout;
+ layout.get<TextSize>() = 12.0f;
+ layout.get<IconTextFit>() = IconTextFitType::Height;
SymbolQuads quads =
getIconQuads(anchor, shapedIcon, line, layout, SymbolPlacementType::Point, shapedText);
@@ -174,13 +174,13 @@ TEST(getIconQuads, style) {
// height x textSize + padding
{
- SymbolLayoutProperties layout;
- layout.textSize = LayoutProperty<float>(12.0f);
- layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Height);
- layout.iconTextFitPadding.value[0] = 5.0f;
- layout.iconTextFitPadding.value[1] = 10.0f;
- layout.iconTextFitPadding.value[2] = 5.0f;
- layout.iconTextFitPadding.value[3] = 10.0f;
+ SymbolLayoutProperties::Evaluated layout;
+ layout.get<TextSize>() = 12.0f;
+ layout.get<IconTextFit>() = IconTextFitType::Height;
+ layout.get<IconTextFitPadding>()[0] = 5.0f;
+ layout.get<IconTextFitPadding>()[1] = 10.0f;
+ layout.get<IconTextFitPadding>()[2] = 5.0f;
+ layout.get<IconTextFitPadding>()[3] = 10.0f;
SymbolQuads quads =
getIconQuads(anchor, shapedIcon, line, layout, SymbolPlacementType::Point, shapedText);
@@ -196,9 +196,9 @@ TEST(getIconQuads, style) {
// both
{
- SymbolLayoutProperties layout;
- layout.textSize = LayoutProperty<float>(24.0f);
- layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Both);
+ SymbolLayoutProperties::Evaluated layout;
+ layout.get<TextSize>() = 24.0f;
+ layout.get<IconTextFit>() = IconTextFitType::Both;
SymbolQuads quads =
getIconQuads(anchor, shapedIcon, line, layout, SymbolPlacementType::Point, shapedText);
@@ -214,9 +214,9 @@ TEST(getIconQuads, style) {
// both x textSize
{
- SymbolLayoutProperties layout;
- layout.textSize = LayoutProperty<float>(12.0f);
- layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Both);
+ SymbolLayoutProperties::Evaluated layout;
+ layout.get<TextSize>() = 12.0f;
+ layout.get<IconTextFit>() = IconTextFitType::Both;
SymbolQuads quads =
getIconQuads(anchor, shapedIcon, line, layout, SymbolPlacementType::Point, shapedText);
@@ -232,13 +232,13 @@ TEST(getIconQuads, style) {
// both x textSize + padding
{
- SymbolLayoutProperties layout;
- layout.textSize = LayoutProperty<float>(12.0f);
- layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Both);
- layout.iconTextFitPadding.value[0] = 5.0f;
- layout.iconTextFitPadding.value[1] = 10.0f;
- layout.iconTextFitPadding.value[2] = 5.0f;
- layout.iconTextFitPadding.value[3] = 10.0f;
+ SymbolLayoutProperties::Evaluated layout;
+ layout.get<TextSize>() = 12.0f;
+ layout.get<IconTextFit>() = IconTextFitType::Both;
+ layout.get<IconTextFitPadding>()[0] = 5.0f;
+ layout.get<IconTextFitPadding>()[1] = 10.0f;
+ layout.get<IconTextFitPadding>()[2] = 5.0f;
+ layout.get<IconTextFitPadding>()[3] = 10.0f;
SymbolQuads quads =
getIconQuads(anchor, shapedIcon, line, layout, SymbolPlacementType::Point, shapedText);
@@ -254,13 +254,13 @@ TEST(getIconQuads, style) {
// both x textSize + padding t/r/b/l
{
- SymbolLayoutProperties layout;
- layout.textSize = LayoutProperty<float>(12.0f);
- layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Both);
- layout.iconTextFitPadding.value[0] = 0.0f;
- layout.iconTextFitPadding.value[1] = 5.0f;
- layout.iconTextFitPadding.value[2] = 10.0f;
- layout.iconTextFitPadding.value[3] = 15.0f;
+ SymbolLayoutProperties::Evaluated layout;
+ layout.get<TextSize>() = 12.0f;
+ layout.get<IconTextFit>() = IconTextFitType::Both;
+ layout.get<IconTextFitPadding>()[0] = 0.0f;
+ layout.get<IconTextFitPadding>()[1] = 5.0f;
+ layout.get<IconTextFitPadding>()[2] = 10.0f;
+ layout.get<IconTextFitPadding>()[3] = 15.0f;
SymbolQuads quads =
getIconQuads(anchor, shapedIcon, line, layout, SymbolPlacementType::Point, shapedText);
diff --git a/test/tile/geojson_tile.test.cpp b/test/tile/geojson_tile.test.cpp
new file mode 100644
index 0000000000..920e946a2b
--- /dev/null
+++ b/test/tile/geojson_tile.test.cpp
@@ -0,0 +1,72 @@
+#include <mbgl/test/util.hpp>
+#include <mbgl/test/fake_file_source.hpp>
+#include <mbgl/test/stub_tile_observer.hpp>
+#include <mbgl/tile/geojson_tile.hpp>
+#include <mbgl/tile/tile_loader_impl.hpp>
+
+#include <mbgl/util/default_thread_pool.hpp>
+#include <mbgl/util/run_loop.hpp>
+#include <mbgl/map/transform.hpp>
+#include <mbgl/style/style.hpp>
+#include <mbgl/style/update_parameters.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/annotation/annotation_manager.hpp>
+
+#include <memory>
+
+using namespace mbgl;
+using namespace mbgl::style;
+
+class GeoJSONTileTest {
+public:
+ FakeFileSource fileSource;
+ TransformState transformState;
+ util::RunLoop loop;
+ ThreadPool threadPool { 1 };
+ AnnotationManager annotationManager { 1.0 };
+ style::Style style { fileSource, 1.0 };
+ Tileset tileset { { "https://example.com" }, { 0, 22 }, "none" };
+
+ style::UpdateParameters updateParameters {
+ 1.0,
+ MapDebugOptions(),
+ transformState,
+ threadPool,
+ fileSource,
+ MapMode::Continuous,
+ annotationManager,
+ style
+ };
+};
+
+TEST(GeoJSONTile, Issue7648) {
+ GeoJSONTileTest test;
+ GeoJSONTile tile(OverscaledTileID(0, 0, 0), "source", test.updateParameters);
+
+ test.style.addLayer(std::make_unique<CircleLayer>("circle", "source"));
+
+ StubTileObserver observer;
+ observer.tileChanged = [&] (const Tile&) {
+ // Once present, the bucket should never "disappear", which would cause
+ // flickering.
+ ASSERT_NE(nullptr, tile.getBucket(*test.style.getLayer("circle")));
+ };
+ tile.setObserver(&observer);
+
+ tile.setPlacementConfig({});
+
+ mapbox::geometry::feature_collection<int16_t> features;
+ features.push_back(mapbox::geometry::feature<int16_t> {
+ mapbox::geometry::point<int16_t>(0, 0)
+ });
+
+ tile.updateData(features);
+ while (!tile.isComplete()) {
+ test.loop.runOnce();
+ }
+
+ tile.updateData(features);
+ while (!tile.isComplete()) {
+ test.loop.runOnce();
+ }
+}
diff --git a/test/tile/raster_tile.test.cpp b/test/tile/raster_tile.test.cpp
index 2a15fd1b99..0d599ceae0 100644
--- a/test/tile/raster_tile.test.cpp
+++ b/test/tile/raster_tile.test.cpp
@@ -3,7 +3,7 @@
#include <mbgl/tile/raster_tile.hpp>
#include <mbgl/tile/tile_loader_impl.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/map/transform.hpp>
#include <mbgl/style/style.hpp>
diff --git a/test/tile/tile_coordinate.test.cpp b/test/tile/tile_coordinate.test.cpp
index 740a03894d..4d58bf8c51 100644
--- a/test/tile/tile_coordinate.test.cpp
+++ b/test/tile/tile_coordinate.test.cpp
@@ -26,8 +26,7 @@ TEST(TileCoordinate, FromLatLng) {
Transform transform(onMapChange);
const double max = util::tileSize;
- const std::array<uint16_t, 2> size { { uint16_t(max), uint16_t(max) } };
- transform.resize(size);
+ transform.resize({ static_cast<uint32_t>(max), static_cast<uint32_t>(max) });
// Center, top-left, bottom-left, bottom-right, top-right edges.
std::vector<std::pair<LatLng, ScreenCoordinate>> edges {
diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp
index c07db42c3c..e34629bdba 100644
--- a/test/tile/vector_tile.test.cpp
+++ b/test/tile/vector_tile.test.cpp
@@ -3,13 +3,19 @@
#include <mbgl/tile/vector_tile.hpp>
#include <mbgl/tile/tile_loader_impl.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/map/transform.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/update_parameters.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/renderer/symbol_bucket.hpp>
+#include <mbgl/text/collision_tile.hpp>
+#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
+#include <memory>
+
using namespace mbgl;
class VectorTileTest {
@@ -47,3 +53,32 @@ TEST(VectorTile, onError) {
tile.onError(std::make_exception_ptr(std::runtime_error("test")));
EXPECT_TRUE(tile.isRenderable());
}
+
+TEST(VectorTile, Issue7615) {
+ VectorTileTest test;
+ VectorTile tile(OverscaledTileID(0, 0, 0), "source", test.updateParameters, test.tileset);
+
+ style::SymbolLayer symbolLayer("symbol", "source");
+ auto symbolBucket = std::make_shared<SymbolBucket>(
+ MapMode::Continuous, style::SymbolLayoutProperties::Evaluated(), false, false);
+
+ // Simulate placement of a symbol layer.
+ tile.onPlacement(GeometryTile::PlacementResult {
+ {{
+ symbolLayer.getID(),
+ symbolBucket
+ }},
+ nullptr,
+ 0
+ });
+
+ // Subsequent onLayout should not cause the existing symbol bucket to be discarded.
+ tile.onLayout(GeometryTile::LayoutResult {
+ {},
+ nullptr,
+ nullptr,
+ 0
+ });
+
+ EXPECT_EQ(symbolBucket.get(), tile.getBucket(symbolLayer));
+}
diff --git a/test/util/http_timeout.test.cpp b/test/util/http_timeout.test.cpp
index 365c40523f..e99c703159 100644
--- a/test/util/http_timeout.test.cpp
+++ b/test/util/http_timeout.test.cpp
@@ -1,6 +1,6 @@
#include <mbgl/test/util.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/http_timeout.hpp>
#include <regex>
#include <iostream>
diff --git a/test/util/image.test.cpp b/test/util/image.test.cpp
index b2814e66da..b15ddc1b3f 100644
--- a/test/util/image.test.cpp
+++ b/test/util/image.test.cpp
@@ -7,7 +7,7 @@
using namespace mbgl;
TEST(Image, PNGRoundTrip) {
- PremultipliedImage rgba { 1, 1 };
+ PremultipliedImage rgba({ 1, 1 });
rgba.data[0] = 128;
rgba.data[1] = 0;
rgba.data[2] = 0;
@@ -21,7 +21,7 @@ TEST(Image, PNGRoundTrip) {
}
TEST(Image, PNGRoundTripAlpha) {
- PremultipliedImage rgba { 1, 1 };
+ PremultipliedImage rgba({ 1, 1 });
rgba.data[0] = 128;
rgba.data[1] = 0;
rgba.data[2] = 0;
@@ -68,26 +68,26 @@ TEST(Image, PNGReadProfileAlpha) {
TEST(Image, PNGTile) {
PremultipliedImage image = decodeImage(util::read_file("test/fixtures/image/tile.png"));
- EXPECT_EQ(256u, image.width);
- EXPECT_EQ(256u, image.height);
+ EXPECT_EQ(256u, image.size.width);
+ EXPECT_EQ(256u, image.size.height);
}
TEST(Image, JPEGTile) {
PremultipliedImage image = decodeImage(util::read_file("test/fixtures/image/tile.jpeg"));
- EXPECT_EQ(256u, image.width);
- EXPECT_EQ(256u, image.height);
+ EXPECT_EQ(256u, image.size.width);
+ EXPECT_EQ(256u, image.size.height);
}
#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(QT_IMAGE_DECODERS)
TEST(Image, WebPTile) {
PremultipliedImage image = decodeImage(util::read_file("test/fixtures/image/tile.webp"));
- EXPECT_EQ(256u, image.width);
- EXPECT_EQ(256u, image.height);
+ EXPECT_EQ(256u, image.size.width);
+ EXPECT_EQ(256u, image.size.height);
}
#endif // !defined(__ANDROID__) && !defined(__APPLE__) && !defined(QT_IMAGE_DECODERS)
TEST(Image, Premultiply) {
- UnassociatedImage rgba { 1, 1 };
+ UnassociatedImage rgba({ 1, 1 });
rgba.data[0] = 255;
rgba.data[1] = 254;
rgba.data[2] = 253;
diff --git a/test/util/mapbox.test.cpp b/test/util/mapbox.test.cpp
index 04c9808ed3..452106d6e6 100644
--- a/test/util/mapbox.test.cpp
+++ b/test/util/mapbox.test.cpp
@@ -1,6 +1,6 @@
#include <mbgl/test/util.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/mapbox.hpp>
#include <mbgl/util/constants.hpp>
#include <regex>
@@ -91,7 +91,7 @@ TEST(Mapbox, SpriteURL) {
"https://api.mapbox.com/styles/v1/mapbox/streets-v8/draft/sprite@2x.png?access_token=key",
mbgl::util::mapbox::normalizeSpriteURL(util::API_BASE_URL, "mapbox://sprites/mapbox/streets-v8/draft@2x.png", "key"));
EXPECT_EQ(
- "mapbox://sprites/mapbox/streets-v9?fresh=true.png",
+ "https://api.mapbox.com/styles/v1/mapbox/streets-v9/sprite?access_token=key&fresh=true.png",
mbgl::util::mapbox::normalizeSpriteURL(util::API_BASE_URL,
"mapbox://sprites/mapbox/streets-v9?fresh=true.png",
"key"));
@@ -139,6 +139,9 @@ TEST(Mapbox, CanonicalURL) {
"mapbox://tiles/a.b/{z}/{x}/{y}.vector.pbf",
mbgl::util::mapbox::canonicalizeTileURL("http://api.mapbox.com/v4/a.b/{z}/{x}/{y}.vector.pbf?access_token=key", SourceType::Vector, 512));
EXPECT_EQ(
+ "mapbox://tiles/a.b/{z}/{x}/{y}.vector.pbf",
+ mbgl::util::mapbox::canonicalizeTileURL("https://api.mapbox.cn/v4/a.b/{z}/{x}/{y}.vector.pbf?access_token=key", SourceType::Vector, 512));
+ EXPECT_EQ(
"mapbox://tiles/a.b,c.d/{z}/{x}/{y}.vector.pbf",
mbgl::util::mapbox::canonicalizeTileURL("http://api.mapbox.com/v4/a.b,c.d/{z}/{x}/{y}.vector.pbf?access_token=key", SourceType::Vector, 512));
EXPECT_EQ(
diff --git a/test/util/memory.test.cpp b/test/util/memory.test.cpp
index a1e47d6c2b..984e7a3e24 100644
--- a/test/util/memory.test.cpp
+++ b/test/util/memory.test.cpp
@@ -2,9 +2,9 @@
#include <mbgl/test/util.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
@@ -56,8 +56,8 @@ public:
}
util::RunLoop runLoop;
- HeadlessBackend backend;
- OffscreenView view{ backend.getContext(), {{ 512, 512 }} };
+ HeadlessBackend backend { test::sharedDisplay() };
+ OffscreenView view{ backend.getContext(), { 512, 512 } };
StubFileSource fileSource;
ThreadPool threadPool { 4 };
@@ -93,7 +93,7 @@ private:
TEST(Memory, Vector) {
MemoryTest test;
- Map map(test.backend, { { 256, 256 } }, 2, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, { 256, 256 }, 2, test.fileSource, test.threadPool, MapMode::Still);
map.setZoom(16); // more map features
map.setStyleURL("mapbox://streets");
@@ -103,7 +103,7 @@ TEST(Memory, Vector) {
TEST(Memory, Raster) {
MemoryTest test;
- Map map(test.backend, { { 256, 256 } }, 2, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, { 256, 256 }, 2, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleURL("mapbox://satellite");
test::render(map, test.view);
@@ -129,7 +129,7 @@ TEST(Memory, Footprint) {
// Warm up buffers and cache.
for (unsigned i = 0; i < 10; ++i) {
- Map map(test.backend, {{ 256, 256 }}, 2, test.fileSource, test.threadPool, MapMode::Still);
+ Map map(test.backend, { 256, 256 }, 2, test.fileSource, test.threadPool, MapMode::Still);
renderMap(map, "mapbox://streets");
renderMap(map, "mapbox://satellite");
};
@@ -143,8 +143,8 @@ TEST(Memory, Footprint) {
long vectorInitialRSS = getRSS();
for (unsigned i = 0; i < runs; ++i) {
- auto vector = std::make_unique<Map>(test.backend, std::array<uint16_t, 2>{ { 256, 256 } },
- 2, test.fileSource, test.threadPool, MapMode::Still);
+ auto vector = std::make_unique<Map>(test.backend, Size{ 256, 256 }, 2, test.fileSource,
+ test.threadPool, MapMode::Still);
renderMap(*vector, "mapbox://streets");
maps.push_back(std::move(vector));
};
@@ -153,8 +153,8 @@ TEST(Memory, Footprint) {
long rasterInitialRSS = getRSS();
for (unsigned i = 0; i < runs; ++i) {
- auto raster = std::make_unique<Map>(test.backend, std::array<uint16_t, 2>{ { 256, 256 } },
- 2, test.fileSource, test.threadPool, MapMode::Still);
+ auto raster = std::make_unique<Map>(test.backend, Size{ 256, 256 }, 2, test.fileSource,
+ test.threadPool, MapMode::Still);
renderMap(*raster, "mapbox://satellite");
maps.push_back(std::move(raster));
};
diff --git a/test/util/merge_lines.test.cpp b/test/util/merge_lines.test.cpp
index db81d8b209..4856a734fe 100644
--- a/test/util/merge_lines.test.cpp
+++ b/test/util/merge_lines.test.cpp
@@ -3,27 +3,29 @@
#include <mbgl/layout/merge_lines.hpp>
#include <mbgl/layout/symbol_feature.hpp>
-const std::u32string aaa = U"a";
-const std::u32string bbb = U"b";
+const std::u16string aaa = u"a";
+const std::u16string bbb = u"b";
+
+using namespace mbgl;
TEST(MergeLines, SameText) {
// merges lines with the same text
std::vector<mbgl::SymbolFeature> input1 = {
- { {{{0, 0}, {1, 0}, {2, 0}}}, aaa, {}, 0 },
- { {{{4, 0}, {5, 0}, {6, 0}}}, bbb, {}, 0 },
- { {{{8, 0}, {9, 0}}}, aaa, {}, 0 },
- { {{{2, 0}, {3, 0}, {4, 0}}}, aaa, {}, 0 },
- { {{{6, 0}, {7, 0}, {8, 0}}}, aaa, {}, 0 },
- { {{{5, 0}, {6, 0}}}, aaa, {}, 0 }
+ { FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{{4, 0}, {5, 0}, {6, 0}}}, bbb, {}, 0 },
+ { FeatureType::LineString, {{{8, 0}, {9, 0}}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{{2, 0}, {3, 0}, {4, 0}}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{{6, 0}, {7, 0}, {8, 0}}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{{5, 0}, {6, 0}}}, aaa, {}, 0 }
};
const std::vector<mbgl::SymbolFeature> expected1 = {
- { {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}}}, aaa, {}, 0 },
- { {{{4, 0}, {5, 0}, {6, 0}}}, bbb, {}, 0 },
- { {{{5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0}}}, aaa, {}, 0 },
- { {{}}, aaa, {}, 0 },
- { {{}}, aaa, {}, 0 },
- { {{}}, aaa, {}, 0 }
+ { FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{{4, 0}, {5, 0}, {6, 0}}}, bbb, {}, 0 },
+ { FeatureType::LineString, {{{5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0}}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{}}, aaa, {}, 0 }
};
mbgl::util::mergeLines(input1);
@@ -36,15 +38,15 @@ TEST(MergeLines, SameText) {
TEST(MergeLines, BothEnds) {
// mergeLines handles merge from both ends
std::vector<mbgl::SymbolFeature> input2 = {
- { {{{0, 0}, {1, 0}, {2, 0}}}, aaa, {}, 0 },
- { {{{4, 0}, {5, 0}, {6, 0}}}, aaa, {}, 0 },
- { {{{2, 0}, {3, 0}, {4, 0}}}, aaa, {}, 0 }
+ { FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{{4, 0}, {5, 0}, {6, 0}}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{{2, 0}, {3, 0}, {4, 0}}}, aaa, {}, 0 }
};
const std::vector<mbgl::SymbolFeature> expected2 = {
- { {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}}}, aaa, {}, 0 },
- { {{}}, aaa, {}, 0 },
- { {{}}, aaa, {}, 0 }
+ { FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{}}, aaa, {}, 0 }
};
mbgl::util::mergeLines(input2);
@@ -57,15 +59,15 @@ TEST(MergeLines, BothEnds) {
TEST(MergeLines, CircularLines) {
// mergeLines handles circular lines
std::vector<mbgl::SymbolFeature> input3 = {
- { {{{0, 0}, {1, 0}, {2, 0}}}, aaa, {}, 0 },
- { {{{2, 0}, {3, 0}, {4, 0}}}, aaa, {}, 0 },
- { {{{4, 0}, {0, 0}}}, aaa, {}, 0 }
+ { FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{{2, 0}, {3, 0}, {4, 0}}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{{4, 0}, {0, 0}}}, aaa, {}, 0 }
};
const std::vector<mbgl::SymbolFeature> expected3 = {
- { {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {0, 0}}}, aaa, {}, 0 },
- { {{}}, aaa, {}, 0 },
- { {{}}, aaa, {}, 0 }
+ { FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {0, 0}}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{}}, aaa, {}, 0 },
+ { FeatureType::LineString, {{}}, aaa, {}, 0 }
};
mbgl::util::mergeLines(input3);
diff --git a/test/util/offscreen_texture.test.cpp b/test/util/offscreen_texture.test.cpp
index 4aded07b2f..31fb985394 100644
--- a/test/util/offscreen_texture.test.cpp
+++ b/test/util/offscreen_texture.test.cpp
@@ -2,16 +2,16 @@
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/context.hpp>
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/offscreen_view.hpp>
#include <mbgl/util/offscreen_texture.hpp>
using namespace mbgl;
TEST(OffscreenTexture, EmptyRed) {
- HeadlessBackend backend;
- OffscreenView view(backend.getContext(), {{ 512, 256 }});
+ HeadlessBackend backend { test::sharedDisplay() };
+ OffscreenView view(backend.getContext(), { 512, 256 });
view.bind();
MBGL_CHECK_ERROR(glClearColor(1.0f, 0.0f, 0.0f, 1.0f));
@@ -67,24 +67,33 @@ struct Buffer {
TEST(OffscreenTexture, RenderToTexture) {
- HeadlessBackend backend;
+ HeadlessBackend backend { test::sharedDisplay() };
auto& context = backend.getContext();
MBGL_CHECK_ERROR(glEnable(GL_BLEND));
MBGL_CHECK_ERROR(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
Shader paintShader(R"MBGL_SHADER(
+#ifdef GL_ES
+precision mediump float;
+#endif
attribute vec2 a_pos;
void main() {
gl_Position = vec4(a_pos, 0, 1);
}
)MBGL_SHADER", R"MBGL_SHADER(
+#ifdef GL_ES
+precision mediump float;
+#endif
void main() {
gl_FragColor = vec4(0, 0.8, 0, 0.8);
}
)MBGL_SHADER");
Shader compositeShader(R"MBGL_SHADER(
+#ifdef GL_ES
+precision mediump float;
+#endif
attribute vec2 a_pos;
varying vec2 v_texcoord;
void main() {
@@ -92,6 +101,9 @@ void main() {
v_texcoord = (a_pos + 1.0) / 2.0;
}
)MBGL_SHADER", R"MBGL_SHADER(
+#ifdef GL_ES
+precision mediump float;
+#endif
uniform sampler2D u_texture;
varying vec2 v_texcoord;
void main() {
@@ -106,22 +118,20 @@ void main() {
// Make sure the texture gets destructed before we call context.reset();
{
- OffscreenView view(context, {{ 512, 256 }});
+ OffscreenView view(context, { 512, 256 });
+ view.bind();
// First, draw red to the bound FBO.
- context.clearColor = { 1, 0, 0, 1 };
- view.bind();
- MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT));
+ context.clear(Color::red(), {}, {});
// Then, create a texture, bind it, and render yellow to that texture. This should not
// affect the originally bound FBO.
- OffscreenTexture texture(context, {{ 128, 128 }});
+ OffscreenTexture texture(context, { 128, 128 });
texture.bind();
- context.clearColor = { 0, 0, 0, 0 };
- MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT));
+ context.clear(Color(), {}, {});
- context.program = paintShader.program;
+ MBGL_CHECK_ERROR(glUseProgram(paintShader.program));
MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, triangleBuffer.buffer));
MBGL_CHECK_ERROR(glEnableVertexAttribArray(paintShader.a_pos));
MBGL_CHECK_ERROR(
@@ -138,8 +148,8 @@ void main() {
test::checkImage("test/fixtures/offscreen_texture/render-to-fbo", image, 0, 0);
// Now, composite the Framebuffer texture we've rendered to onto the main FBO.
- context.program = compositeShader.program;
context.bindTexture(texture.getTexture(), 0, gl::TextureFilter::Linear);
+ MBGL_CHECK_ERROR(glUseProgram(compositeShader.program));
MBGL_CHECK_ERROR(glUniform1i(u_texture, 0));
MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, viewportBuffer.buffer));
MBGL_CHECK_ERROR(glEnableVertexAttribArray(compositeShader.a_pos));
diff --git a/test/util/text_conversions.test.cpp b/test/util/text_conversions.test.cpp
index 19e30d9f3d..442a49fa0c 100644
--- a/test/util/text_conversions.test.cpp
+++ b/test/util/text_conversions.test.cpp
@@ -2,7 +2,7 @@
#include <mbgl/test/util.hpp>
#include <mbgl/util/utf.hpp>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/platform.hpp>
using namespace mbgl;
diff --git a/test/util/tile_cover.test.cpp b/test/util/tile_cover.test.cpp
index cc183509d9..809b7df9f2 100644
--- a/test/util/tile_cover.test.cpp
+++ b/test/util/tile_cover.test.cpp
@@ -29,7 +29,9 @@ TEST(TileCover, WorldZ0) {
TEST(TileCover, Pitch) {
Transform transform;
- transform.resize({ { 512, 512 } });
+ transform.resize({ 512, 512 });
+ // slightly offset center so that tile order is better defined
+ transform.setLatLng({ 0.01, -0.01 });
transform.setZoom(2);
transform.setPitch(40.0 * M_PI / 180.0);
diff --git a/test/util/url.test.cpp b/test/util/url.test.cpp
new file mode 100644
index 0000000000..00b761ce2e
--- /dev/null
+++ b/test/util/url.test.cpp
@@ -0,0 +1,207 @@
+#include <mbgl/test/util.hpp>
+
+#include <mbgl/util/url.hpp>
+
+#include <memory>
+
+using namespace mbgl::util;
+
+TEST(URL, isURL) {
+ EXPECT_TRUE(isURL("mapbox://foo"));
+ EXPECT_TRUE(isURL("mapbox://"));
+ EXPECT_TRUE(isURL("mapbox-test-scheme://foo"));
+ EXPECT_TRUE(isURL("mapbox+style://foo"));
+ EXPECT_TRUE(isURL("mapbox-2.0://foo"));
+ EXPECT_TRUE(isURL("mapbox99://foo"));
+
+ EXPECT_FALSE(isURL("mapbox:/"));
+ EXPECT_FALSE(isURL(" mapbox://"));
+ EXPECT_FALSE(isURL("://"));
+ EXPECT_FALSE(isURL("mapbox"));
+ EXPECT_FALSE(isURL("mapbox:foo"));
+ EXPECT_FALSE(isURL("mapbox:/foo"));
+ EXPECT_FALSE(isURL("test/mapbox://foo"));
+ EXPECT_FALSE(isURL("123://foo"));
+}
+
+TEST(URL, Scheme) {
+ EXPECT_EQ(URL::Segment({ 0, 4 }), URL("http://example.com/test?query=foo").scheme);
+ EXPECT_EQ(URL::Segment({ 0, 0 }), URL("htt").scheme);
+ EXPECT_EQ(URL::Segment({ 0, 6 }), URL("mapbox://").scheme);
+ EXPECT_EQ(URL::Segment({ 0, 6 }), URL("mapbox:/#").scheme);
+ EXPECT_EQ(URL::Segment({ 0, 0 }), URL("://").scheme);
+ EXPECT_EQ(URL::Segment({ 0, 0 }), URL("").scheme);
+ EXPECT_EQ(URL::Segment({ 0, 0 }), URL("http?query://baz").scheme);
+ EXPECT_EQ(URL::Segment({ 0, 0 }), URL(":::").scheme);
+ EXPECT_EQ(URL::Segment({ 0, 4 }), URL("data:,Hello%2C%20World!").scheme);
+ EXPECT_EQ(URL::Segment({ 0, 4 }), URL("data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D").scheme);
+}
+
+TEST(URL, Query) {
+ EXPECT_EQ(URL::Segment({ 23, 10 }), URL("http://example.com/test?query=foo").query);
+ EXPECT_EQ(URL::Segment({ 23, 10 }), URL("http://example.com/test?query=foo#page-2").query);
+ EXPECT_EQ(URL::Segment({ 23, 0 }), URL("http://example.com/test#query=foo?page-2").query);
+ EXPECT_EQ(URL::Segment({ 0, 10 }), URL("?query=foo").query);
+ EXPECT_EQ(URL::Segment({ 0, 10 }), URL("?query=foo#bar").query);
+ EXPECT_EQ(URL::Segment({ 0, 0 }), URL("#?query=foo#bar").query);
+ EXPECT_EQ(URL::Segment({ 4, 12 }), URL("http?query://baz").query);
+ EXPECT_EQ(URL::Segment({ 9, 4 }), URL("mapbox://?bar").query);
+ EXPECT_EQ(URL::Segment({ 12, 0 }), URL("mapbox://bar").query);
+ EXPECT_EQ(URL::Segment({ 0, 0 }), URL("").query);
+ EXPECT_EQ(URL::Segment({ 3, 0 }), URL(":::").query);
+ EXPECT_EQ(URL::Segment({ 23, 0 }), URL("data:,Hello%2C%20World!").query);
+ EXPECT_EQ(URL::Segment({ 47, 0 }), URL("data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D").query);
+}
+
+TEST(URL, Domain) {
+ EXPECT_EQ(URL::Segment({ 7, 11 }), URL("http://example.com/test?query=foo").domain);
+ EXPECT_EQ(URL::Segment({ 5, 11 }), URL("http:example.com/test?query=foo").domain);
+ EXPECT_EQ(URL::Segment({ 0, 3 }), URL("htt").domain);
+ EXPECT_EQ(URL::Segment({ 0, 4 }), URL("http?query://baz").domain);
+ EXPECT_EQ(URL::Segment({ 0, 6 }), URL("domain/foo?bar").domain);
+ EXPECT_EQ(URL::Segment({ 7, 0 }), URL("http://").domain);
+ EXPECT_EQ(URL::Segment({ 7, 6 }), URL("http://domain").domain);
+ EXPECT_EQ(URL::Segment({ 7, 6 }), URL("http://domain#bar").domain);
+ EXPECT_EQ(URL::Segment({ 7, 6 }), URL("http://domain/").domain);
+ EXPECT_EQ(URL::Segment({ 7, 6 }), URL("http://domain/foo").domain);
+ EXPECT_EQ(URL::Segment({ 7, 6 }), URL("http://domain/foo?").domain);
+ EXPECT_EQ(URL::Segment({ 0, 1 }), URL("h##p://domain/foo?bar").domain);
+ EXPECT_EQ(URL::Segment({ 7, 6 }), URL("http://domain/foo?bar").domain);
+ EXPECT_EQ(URL::Segment({ 7, 6 }), URL("http://domain/?").domain);
+ EXPECT_EQ(URL::Segment({ 7, 6 }), URL("http://domain?").domain);
+ EXPECT_EQ(URL::Segment({ 7, 6 }), URL("http://domain?foo").domain);
+ EXPECT_EQ(URL::Segment({ 3, 0 }), URL(":::").domain);
+ EXPECT_EQ(URL::Segment({ 5, 0 }), URL("data:,Hello%2C%20World!").domain);
+ EXPECT_EQ(URL::Segment({ 5, 17 }), URL("data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D").domain);
+}
+
+TEST(URL, Path) {
+ EXPECT_EQ(URL::Segment({ 19, 4 }), URL("http://example.com/test?query=foo").path);
+ EXPECT_EQ(URL::Segment({ 19, 4 }), URL("http://example.com/test?query=foo#bar").path);
+ EXPECT_EQ(URL::Segment({ 19, 4 }), URL("http://example.com/test#bar").path);
+ EXPECT_EQ(URL::Segment({ 18, 0 }), URL("http://example.com?query=foo").path);
+ EXPECT_EQ(URL::Segment({ 18, 0 }), URL("http://example.com#?query=foo").path);
+ EXPECT_EQ(URL::Segment({ 19, 0 }), URL("http://example.com/?query=foo").path);
+ EXPECT_EQ(URL::Segment({ 3, 0 }), URL(":::").path);
+ EXPECT_EQ(URL::Segment({ 13, 0 }), URL("http://domain").path);
+ EXPECT_EQ(URL::Segment({ 7, 3 }), URL("domain/foo?bar").path);
+ EXPECT_EQ(URL::Segment({ 6, 17 }), URL("data:,Hello%2C%20World!").path);
+ EXPECT_EQ(URL::Segment({ 23, 24 }), URL("data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D").path);
+}
+
+auto URLPath = [](const char* str) { const URL url(str); return Path(str, url.path.first, url.path.second); };
+
+TEST(Path, Directory) {
+ EXPECT_EQ(Path::Segment({ 0, 8 }), Path("foo/bar/baz.ext").directory);
+ EXPECT_EQ(Path::Segment({ 0, 8 }), Path("foo.bar/baz.ext").directory);
+ EXPECT_EQ(Path::Segment({ 0, 8 }), Path("foo.bar/baz").directory);
+ EXPECT_EQ(Path::Segment({ 0, 8 }), Path("foo/bar/.ext").directory);
+ EXPECT_EQ(Path::Segment({ 0, 4 }), Path("foo/bar@2x.png").directory);
+ EXPECT_EQ(Path::Segment({ 0, 4 }), Path("foo/b").directory);
+ EXPECT_EQ(Path::Segment({ 0, 4 }), Path("foo/").directory);
+ EXPECT_EQ(Path::Segment({ 0, 0 }), Path("foo").directory);
+ EXPECT_EQ(Path::Segment({ 0, 0 }), Path("foo.png").directory);
+ EXPECT_EQ(Path::Segment({ 0, 0 }), Path("").directory);
+}
+
+TEST(Path, URLDirectory) {
+ EXPECT_EQ(Path::Segment({ 19, 8 }), URLPath("http://example.com/foo/bar/baz.ext").directory);
+ EXPECT_EQ(Path::Segment({ 19, 8 }), URLPath("http://example.com/foo/bar/baz.ext?query=foo.bar").directory);
+ EXPECT_EQ(Path::Segment({ 19, 8 }), URLPath("http://example.com/foo.bar/baz.ext").directory);
+ EXPECT_EQ(Path::Segment({ 19, 8 }), URLPath("http://example.com/foo.bar/baz.ext?query=foo.bar").directory);
+ EXPECT_EQ(Path::Segment({ 19, 8 }), URLPath("http://example.com/foo.bar/baz").directory);
+ EXPECT_EQ(Path::Segment({ 19, 8 }), URLPath("http://example.com/foo.bar/baz?query=foo.bar").directory);
+ EXPECT_EQ(Path::Segment({ 19, 8 }), URLPath("http://example.com/foo/bar/.ext").directory);
+ EXPECT_EQ(Path::Segment({ 19, 8 }), URLPath("http://example.com/foo/bar/.ext?query=foo.bar").directory);
+ EXPECT_EQ(Path::Segment({ 19, 4 }), URLPath("http://example.com/foo/bar@2x.png").directory);
+ EXPECT_EQ(Path::Segment({ 19, 4 }), URLPath("http://example.com/foo/bar@2x.png?query=foo.bar").directory);
+ EXPECT_EQ(Path::Segment({ 19, 4 }), URLPath("http://example.com/foo/b").directory);
+ EXPECT_EQ(Path::Segment({ 19, 4 }), URLPath("http://example.com/foo/b?query=foo.bar").directory);
+ EXPECT_EQ(Path::Segment({ 19, 4 }), URLPath("http://example.com/foo/").directory);
+ EXPECT_EQ(Path::Segment({ 19, 4 }), URLPath("http://example.com/foo/?query=foo.bar").directory);
+ EXPECT_EQ(Path::Segment({ 19, 0 }), URLPath("http://example.com/foo").directory);
+ EXPECT_EQ(Path::Segment({ 19, 0 }), URLPath("http://example.com/foo?query=foo.bar").directory);
+ EXPECT_EQ(Path::Segment({ 19, 0 }), URLPath("http://example.com/foo.png").directory);
+ EXPECT_EQ(Path::Segment({ 19, 0 }), URLPath("http://example.com/foo.png?query=foo.bar").directory);
+ EXPECT_EQ(Path::Segment({ 19, 0 }), URLPath("http://example.com/").directory);
+ EXPECT_EQ(Path::Segment({ 19, 0 }), URLPath("http://example.com/?query=foo.bar").directory);
+ EXPECT_EQ(Path::Segment({ 18, 0 }), URLPath("http://example.com").directory);
+ EXPECT_EQ(Path::Segment({ 18, 0 }), URLPath("http://example.com?query=foo.bar").directory);
+}
+
+TEST(Path, Extension) {
+ EXPECT_EQ(Path::Segment({ 11, 4 }), Path("foo/bar/baz.ext").extension);
+ EXPECT_EQ(Path::Segment({ 11, 4 }), Path("foo.bar/baz.ext").extension);
+ EXPECT_EQ(Path::Segment({ 18, 4 }), Path("foo.bar/baz.vector.pbf").extension);
+ EXPECT_EQ(Path::Segment({ 11, 0 }), Path("foo.bar/baz").extension);
+ EXPECT_EQ(Path::Segment({ 8, 4 }), Path("foo/bar/.ext").extension);
+ EXPECT_EQ(Path::Segment({ 7, 7 }), Path("foo/bar@2x.png").extension);
+ EXPECT_EQ(Path::Segment({ 5, 0 }), Path("foo/b").extension);
+ EXPECT_EQ(Path::Segment({ 4, 0 }), Path("foo/").extension);
+ EXPECT_EQ(Path::Segment({ 3, 0 }), Path("foo").extension);
+ EXPECT_EQ(Path::Segment({ 3, 4 }), Path("foo.png").extension);
+ EXPECT_EQ(Path::Segment({ 0, 0 }), Path("").extension);
+}
+
+TEST(Path, URLExtension) {
+ EXPECT_EQ(Path::Segment({ 30, 4 }), URLPath("http://example.com/foo/bar/baz.ext").extension);
+ EXPECT_EQ(Path::Segment({ 30, 4 }), URLPath("http://example.com/foo/bar/baz.ext?query=foo.bar").extension);
+ EXPECT_EQ(Path::Segment({ 30, 4 }), URLPath("http://example.com/foo.bar/baz.ext").extension);
+ EXPECT_EQ(Path::Segment({ 30, 4 }), URLPath("http://example.com/foo.bar/baz.ext?query=foo.bar").extension);
+ EXPECT_EQ(Path::Segment({ 30, 0 }), URLPath("http://example.com/foo.bar/baz").extension);
+ EXPECT_EQ(Path::Segment({ 30, 0 }), URLPath("http://example.com/foo.bar/baz?query=foo.bar").extension);
+ EXPECT_EQ(Path::Segment({ 27, 4 }), URLPath("http://example.com/foo/bar/.ext").extension);
+ EXPECT_EQ(Path::Segment({ 27, 4 }), URLPath("http://example.com/foo/bar/.ext?query=foo.bar").extension);
+ EXPECT_EQ(Path::Segment({ 26, 7 }), URLPath("http://example.com/foo/bar@2x.png").extension);
+ EXPECT_EQ(Path::Segment({ 26, 7 }), URLPath("http://example.com/foo/bar@2x.png?query=foo.bar").extension);
+ EXPECT_EQ(Path::Segment({ 24, 0 }), URLPath("http://example.com/foo/b").extension);
+ EXPECT_EQ(Path::Segment({ 24, 0 }), URLPath("http://example.com/foo/b?query=foo.bar").extension);
+ EXPECT_EQ(Path::Segment({ 23, 0 }), URLPath("http://example.com/foo/").extension);
+ EXPECT_EQ(Path::Segment({ 23, 0 }), URLPath("http://example.com/foo/?query=foo.bar").extension);
+ EXPECT_EQ(Path::Segment({ 22, 0 }), URLPath("http://example.com/foo").extension);
+ EXPECT_EQ(Path::Segment({ 22, 0 }), URLPath("http://example.com/foo?query=foo.bar").extension);
+ EXPECT_EQ(Path::Segment({ 22, 4 }), URLPath("http://example.com/foo.png").extension);
+ EXPECT_EQ(Path::Segment({ 22, 4 }), URLPath("http://example.com/foo.png?query=foo.bar").extension);
+ EXPECT_EQ(Path::Segment({ 19, 0 }), URLPath("http://example.com/").extension);
+ EXPECT_EQ(Path::Segment({ 19, 0 }), URLPath("http://example.com/?query=foo.bar").extension);
+ EXPECT_EQ(Path::Segment({ 18, 0 }), URLPath("http://example.com").extension);
+ EXPECT_EQ(Path::Segment({ 18, 0 }), URLPath("http://example.com?query=foo.bar").extension);
+}
+
+TEST(Path, Filename) {
+ EXPECT_EQ(Path::Segment({ 8, 3 }), Path("foo/bar/baz.ext").filename);
+ EXPECT_EQ(Path::Segment({ 8, 3 }), Path("foo.bar/baz.ext").filename);
+ EXPECT_EQ(Path::Segment({ 8, 3 }), Path("foo.bar/baz").filename);
+ EXPECT_EQ(Path::Segment({ 8, 0 }), Path("foo/bar/.ext").filename);
+ EXPECT_EQ(Path::Segment({ 4, 3 }), Path("foo/bar@2x.png").filename);
+ EXPECT_EQ(Path::Segment({ 4, 1 }), Path("foo/b").filename);
+ EXPECT_EQ(Path::Segment({ 4, 0 }), Path("foo/").filename);
+ EXPECT_EQ(Path::Segment({ 0, 3 }), Path("foo").filename);
+ EXPECT_EQ(Path::Segment({ 0, 3 }), Path("foo.png").filename);
+ EXPECT_EQ(Path::Segment({ 0, 0 }), Path("").filename);
+}
+
+TEST(Path, URLFilename) {
+ EXPECT_EQ(Path::Segment({ 27, 3 }), URLPath("http://example.com/foo/bar/baz.ext").filename);
+ EXPECT_EQ(Path::Segment({ 27, 3 }), URLPath("http://example.com/foo/bar/baz.ext?query=foo.bar").filename);
+ EXPECT_EQ(Path::Segment({ 27, 3 }), URLPath("http://example.com/foo.bar/baz.ext").filename);
+ EXPECT_EQ(Path::Segment({ 27, 3 }), URLPath("http://example.com/foo.bar/baz.ext?query=foo.bar").filename);
+ EXPECT_EQ(Path::Segment({ 27, 3 }), URLPath("http://example.com/foo.bar/baz").filename);
+ EXPECT_EQ(Path::Segment({ 27, 3 }), URLPath("http://example.com/foo.bar/baz?query=foo.bar").filename);
+ EXPECT_EQ(Path::Segment({ 27, 0 }), URLPath("http://example.com/foo/bar/.ext").filename);
+ EXPECT_EQ(Path::Segment({ 27, 0 }), URLPath("http://example.com/foo/bar/.ext?query=foo.bar").filename);
+ EXPECT_EQ(Path::Segment({ 23, 3 }), URLPath("http://example.com/foo/bar@2x.png").filename);
+ EXPECT_EQ(Path::Segment({ 23, 3 }), URLPath("http://example.com/foo/bar@2x.png?query=foo.bar").filename);
+ EXPECT_EQ(Path::Segment({ 23, 1 }), URLPath("http://example.com/foo/b").filename);
+ EXPECT_EQ(Path::Segment({ 23, 1 }), URLPath("http://example.com/foo/b?query=foo.bar").filename);
+ EXPECT_EQ(Path::Segment({ 23, 0 }), URLPath("http://example.com/foo/").filename);
+ EXPECT_EQ(Path::Segment({ 23, 0 }), URLPath("http://example.com/foo/?query=foo.bar").filename);
+ EXPECT_EQ(Path::Segment({ 19, 3 }), URLPath("http://example.com/foo").filename);
+ EXPECT_EQ(Path::Segment({ 19, 3 }), URLPath("http://example.com/foo?query=foo.bar").filename);
+ EXPECT_EQ(Path::Segment({ 19, 3 }), URLPath("http://example.com/foo.png").filename);
+ EXPECT_EQ(Path::Segment({ 19, 3 }), URLPath("http://example.com/foo.png?query=foo.bar").filename);
+ EXPECT_EQ(Path::Segment({ 19, 0 }), URLPath("http://example.com/").filename);
+ EXPECT_EQ(Path::Segment({ 19, 0 }), URLPath("http://example.com/?query=foo.bar").filename);
+ EXPECT_EQ(Path::Segment({ 18, 0 }), URLPath("http://example.com").filename);
+ EXPECT_EQ(Path::Segment({ 18, 0 }), URLPath("http://example.com?query=foo.bar").filename);
+}